欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go 在 MongoDB 中常用查询与修改的操作

程序员文章站 2022-03-07 12:45:42
以下所有例子中结构定义如下:type user struct { id_ bson.objectid `bson:"_id"` name string `bson:"name"` a...

以下所有例子中结构定义如下:

type user struct {
    id_ bson.objectid `bson:"_id"`
    name string `bson:"name"`
    age int `bson:"age"`
    joinedat time.time `bson:"joined_at"`
    interests []string `bson:"interests"`
    num []int `bson:"num"`
}

1、查询

通过func (c *collection) find(query interface{}) *query来进行查询,返回的query struct可以有附加各种条件来进行过滤。

通过query.all()可以获得所有结果,通过query.one()可以获得一个结果,注意如果没有数据或者数量超过一个,one()会报错。

条件用bson.m{key: value},注意key必须用mongodb中的字段名,而不是struct的字段名。

1.1、查询所有

var users []user
c.find(nil).all(&users)

上面代码可以把所有users都查出来:

1.2、根据objectid查询

id := "5204af979955496907000001"
objectid := bson.objectidhex(id)
user := new(user)
c.find(bson.m{"_id": objectid}).one(&user)

更简单的方式是直接用findid()方法:

c.findid(objectid).one(&user)

注意这里没有处理err。当找不到的时候用one()方法会出错。

1.3、单条件查询

=($eq)
c.find(bson.m{"name": "jimmy kuu"}).all(&users)
!=($ne)
c.find(bson.m{"name": bson.m{"$ne": "jimmy kuu"}}).all(&users)
>($gt)
c.find(bson.m{"age": bson.m{"$gt": 32}}).all(&users)
<($lt)
c.find(bson.m{"age": bson.m{"$lt": 32}}).all(&users)
>=($gte)
c.find(bson.m{"age": bson.m{"$gte": 33}}).all(&users)
<=($lte)
c.find(bson.m{"age": bson.m{"$lte": 31}}).all(&users)
in($in)
c.find(bson.m{"name": bson.m{"$in": []string{"jimmy kuu", "tracy yu"}}}).all(&users)

1.4、多条件查询

and($and)
c.find(bson.m{"name": "jimmy kuu", "age": 33}).all(&users)
or($or)
c.find(bson.m{"$or": []bson.m{bson.m{"name": "jimmy kuu"}, bson.m{"age": 31}}}).all(&users)

2、修改

通过func (*collection) update来进行修改操作。

func (c *collection) update(selector interface{}, change interface{}) error

注意修改单个或多个字段需要通过$set操作符号,否则集合会被替换。

2.1、($set)

//修改字段的值
c.update(
    bson.m{"_id": bson.objectidhex("5204af979955496907000001")},
    bson.m{"$set": bson.m{ "name": "jimmy gu", "age": 34 }}
)

2.2、inc($inc)

//字段增加值
c.update(
    bson.m{"_id": bson.objectidhex("5204af979955496907000001")},
    bson.m{"$inc": bson.m{ "age": -1 }}
)
//字段num数组第三个数增加值
c.update(
    bson.m{"_id": bson.objectidhex("5204af979955496907000001")},
    bson.m{"$inc": bson.m{ "num." + strconv.itoa(2): 1 }})

2.3、push($push)

//从数组中增加一个元素
c.update(
    bson.m{"_id": bson.objectidhex("5204af979955496907000001")},
    bson.m{"$push": bson.m{ "interests": "golang" }}
)

2.4、pull($pull)

//从数组中删除一个元素
c.update(
    bson.m{"_id": bson.objectidhex("5204af979955496907000001")},
    bson.m{"$pull": bson.m{ "interests": "golang" }}
)

2.5、删除

c.remove(bson.m{"name": "jimmy kuu"})

补充:golang mongodb查找find demo

使用gopkg.in/mgo.v2库操作,插入操作主要使用mongodb中collection对象的find方法,函数原型:

func (c *collection) find(query interface{}) *query

查找的时候find的参数都会用bson.m类型

type m map[string]interface{}

例如:bson.m{"name": "tom"}相当直接mongodb的查询条件{"name": "tom"}

统一封装下getdb方法

package main
 
import (
     "fmt"
 
     "gopkg.in/mgo.v2"
     "gopkg.in/mgo.v2/bson"
)
 
// get mongodb db
func getdb() *mgo.database {
     session, err := mgo.dial( "172.16.27.134:10001" )
     if err != nil {
         panic(err)
     }
 
     session.setmode(mgo.monotonic, true)
     db := session.db( "test" )
     return db
}

查找单条记录

func findone() {
     db := getdb()
 
     c := db.c( "user" )
 
     // 用struct接收,一般情况下都会这样处理
     type user struct {
         name string  "bson:`name`"
         age  int     "bson:`age`"
     }
     user := user{}
     err := c.find(bson.m{ "name" :  "tom" }).one(&user)
     if err != nil {
         panic(err)
     }
     fmt.println(user)
     // output: {tom 20}
 
     // 用bson.m结构接收,当你不了解返回的数据结构格式时,可以用这个先查看,然后再定义struct格式
     // 在处理mongodb组合查询时,经常这么干
     result := bson.m{}
     err = c.find(nil).one(&result)
     if err != nil {
         panic(err)
     }
     fmt.println(result)
     // output: map[_id:objectidhex("56fdce98189df8759fd61e5b") name:tom age:20]
 
}

查找多条记录

func findmuit() {
     db := getdb()
 
     c := db.c( "user" )
 
     // 使用all方法,一次性消耗较多内存,如果数据较多,可以考虑使用迭代器
     type user struct {
         id   bson.objectid `bson: "_id,omitempty" `
         name string         "bson:`name`"
         age  int            "bson:`age`"
     }
     var users []user
     err := c.find(nil).all(&users)
     if err != nil {
         panic(err)
     }
     fmt.println(users)
     // output: [{objectidhex("56fdce98189df8759fd61e5b") tom 20}...]
 
     // 使用迭代器获取数据可以避免一次占用较大内存
     var user user
     iter := c.find(nil).iter()
     for iter.next(&user) {
         fmt.println(user)
     }
     // output:
     // {objectidhex("56fdce98189df8759fd61e5b") tom 20}
     // {objectidhex("56fdce98189df8759fd61e5c") tom 20}
     // ...
}

查找指定字段

主要使用select函数:

func (q *query) select(selector interface{}) *query
func findfield() {
     db := getdb()
 
     c := db.c( "user" )
 
     // 只读取name字段
     type user struct {
         name string  "bson:`name`"
     }
     var users []user
     err := c.find(bson.m{}).select(bson.m{ "name" :  1 }).all(&users)
     if err != nil {
         panic(err)
     }
     fmt.println(users)
     // output: [{tom} {tom} {anny}...]
 
     // 只排除_id字段
     type user2 struct {
         name string  "bson:`name`"
         age  int     "bson:`age`"
     }
     var users2 []user2
     err = c.find(bson.m{}).select(bson.m{ "_id" :  0 }).all(&users2)
     if err != nil {
         panic(err)
     }
     fmt.println(users2)
     // output: [{tom 20} {tom 20} {anny 28}...]
 
}

查询嵌套格式数据

func findnesting() {
     db := getdb()
 
     c := db.c( "user" )
 
     // 使用嵌套的struct接收数据
     type user struct {
         name string  "bson:`name`"
         age  int     "bson:`age`"
         toys []struct {
             name string  "bson:`name`"
         }
     }
     var users user
     // 只查询toys字段存在的
     err := c.find(bson.m{ "toys" : bson.m{ "$exists" : true}}).one(&users)
     if err != nil {
         panic(err)
     }
     fmt.println(users)
     // output: {tom 20 [{dog}]}
}

查找数据总数

func count() {
     db := getdb()
 
     c := db.c( "user" )
 
     // 查找表总数
     count, err := c.count()
     if err != nil {
         panic(err)
     }
     fmt.println(count)
     // output: 8
 
     // 结合find条件查找
     count, err = c.find(bson.m{ "name" :  "tom" }).count()
     if err != nil {
         panic(err)
     }
     fmt.println(count)
     // output: 6
 
}

对数据进行排序

使用sort函数

func (q *query) sort(fields ...string) *query
func findsort() {
     db := getdb() 
     c := db.c( "user" ) 
     type user struct {
         id   bson.objectid `bson: "_id,omitempty" `
         name string         "bson:`name`"
         age  int            "bson:`age`"
     }
     var users []user
     // 按照age字段降序排列,如果升序去掉横线"-"就可以了
     err := c.find(nil).sort( "-age" ).all(&users)
     if err != nil {
         panic(err)
     }
     fmt.println(users)
     // output:
     // [{objectidhex("56fdce98189df8759fd61e5d") anny 28} ...]
     // ...
}

分页查询

使用skip函数和limit函数

func (q *query) skip(n int) *query
func (q *query) limit(n int) *query
func findpage() {
     db := getdb() 
     c := db.c( "user" ) 
     type user struct {
         id   bson.objectid `bson: "_id,omitempty" `
         name string         "bson:`name`"
         age  int            "bson:`age`"
     }
     var users []user
     // 表示从偏移位置为2的地方开始取两条记录
     err := c.find(nil).sort( "-age" ).skip( 2 ).limit( 2 ).all(&users)
     if err != nil {
         panic(err)
     }
     fmt.println(users)
     // output:
     // [{objectidhex("56fdce98189df8759fd61e5d") anny 20} ...]
     // ...
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。