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

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

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} ...]
     // ...
}

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

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐