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


Posted in Golang onMay 07, 2021

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

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

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

Golang 相关文章推荐
golang 生成对应的数据表struct定义操作
Apr 28 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
解决Goland 同一个package中函数互相调用的问题
May 06 Golang
golang中的并发和并行
May 08 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
golang内置函数len的小技巧
Jul 25 Golang
Golang原生rpc(rpc服务端源码解读)
Apr 07 Golang
Go web入门Go pongo2模板引擎
May 20 Golang
详解Go语言中Get/Post请求测试
Jun 01 Golang
Go调用Rust方法及外部函数接口前置
Jun 14 Golang
golang 实现时间戳和时间的转化
May 07 #Golang
Golang Gob编码(gob包的使用详解)
May 07 #Golang
go mod 安装依赖 unkown revision问题的解决方案
解决golang 关于全局变量的坑
May 06 #Golang
Goland使用Go Modules创建/管理项目的操作
解决goland 导入项目后import里的包报红问题
Go 自定义package包设置与导入操作
You might like
在Zeus Web Server中安装PHP语言支持
2006/10/09 PHP
PHP队列用法实例
2014/11/05 PHP
php smtp实现发送邮件功能
2017/06/22 PHP
PPK 谈 JavaScript 的 this 关键字 [翻译]
2009/09/29 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
Jquery实现图片放大镜效果的思路及代码(自写)
2013/10/18 Javascript
原生JavaScript编写俄罗斯方块
2015/03/30 Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
2015/11/25 Javascript
详解JS几种变量交换方式以及性能分析对比
2016/11/25 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
mui框架 页面无法滚动的解决方法(推荐)
2018/01/25 Javascript
webpack中使用iconfont字体图标的方法
2018/02/22 Javascript
Webpack中雪碧图插件使用详解
2018/05/25 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
2018/06/28 Javascript
vue组件从开发到发布的实现步骤
2018/11/11 Javascript
详解关于JSON.parse()和JSON.stringify()的性能小测试
2019/03/14 Javascript
解决IOS端微信H5页面软键盘弹起后页面下方留白的问题
2019/06/05 Javascript
解决vue addRoutes不生效问题
2020/08/04 Javascript
Nuxt的路由配置和参数传递方式
2020/11/06 Javascript
Vue + ts实现轮播插件的示例
2020/11/10 Javascript
[56:14]Fnatic vs OG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python os模块介绍
2014/11/30 Python
python中随机函数random用法实例
2015/04/30 Python
python操作文件的参数整理
2019/06/11 Python
python通过实例讲解反射机制
2019/10/17 Python
pytorch ImageFolder的覆写实例
2020/02/20 Python
关于Python字符串显示u...的解决方式
2020/03/06 Python
基于 Python 实践感知器分类算法
2021/01/07 Python
VSCode 自定义html5模板的实现
2019/12/05 HTML / CSS
广州足迹信息技术有限公司Java软件工程师试题
2014/02/15 面试题
会计自我鉴定
2013/11/02 职场文书
2014年销售部工作总结
2014/12/01 职场文书
先进党支部事迹材料
2014/12/24 职场文书
同学毕业留言寄语
2015/02/27 职场文书
博士生专家推荐信
2015/03/25 职场文书
党支部半年考察意见
2015/06/01 职场文书