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 相关文章推荐
Go语言使用select{}阻塞main函数介绍
Apr 25 Golang
golang import自定义包方式
Apr 29 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
Golang 编译成DLL文件的操作
May 06 Golang
goland 设置project gopath的操作
May 06 Golang
使用golang编写一个并发工作队列
May 08 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
Go 语言下基于Redis分布式锁的实现方式
Jun 28 Golang
Go 通过结构struct实现接口interface的问题
Oct 05 Golang
golang中的struct操作
Nov 11 Golang
Golang 实现 WebSockets 之创建 WebSockets
Apr 24 Golang
Go中使用gjson来操作JSON数据的实现
Aug 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
PHP概率计算函数汇总
2015/09/13 PHP
PHP绕过open_basedir限制操作文件的方法
2018/06/10 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
JavaScript 高级篇之闭包、模拟类,继承(五)
2012/04/07 Javascript
js数组转json并在后台对其解析具体实现
2013/11/20 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
JavaScript实现获取dom中class的方法
2015/02/09 Javascript
JavaScript根据CSS的Media Queries来判断浏览设备的方法
2016/05/10 Javascript
jquery 获取select数组与name数组长度的实现代码
2016/06/20 Javascript
AngularJs html compiler详解及示例代码
2016/09/01 Javascript
jQuery动态修改字体大小的方法【测试可用】
2016/09/09 Javascript
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
vue+vuex+axio从后台获取数据存入vuex实现组件之间共享数据
2017/04/22 Javascript
vue实现全选、反选功能
2020/11/17 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
2017/06/19 Javascript
vue cli升级webapck4总结
2018/04/04 Javascript
angularJs在多个控制器中共享服务数据的方法
2018/09/30 Javascript
Python中的类学习笔记
2014/09/23 Python
如何在python中使用selenium的示例
2017/12/26 Python
对Python中内置异常层次结构详解
2018/10/18 Python
python实现dijkstra最短路由算法
2019/01/17 Python
Django 响应数据response的返回源码详解
2019/08/06 Python
Python魔术方法专题
2020/06/19 Python
美国最大网上鞋店:Zappos
2016/07/25 全球购物
定义一结构体数组表示分数,并求两个分数相加之和
2013/06/11 面试题
保卫科工作岗位职责
2014/03/01 职场文书
同学会主持词
2014/03/18 职场文书
财务内勤岗位职责
2014/04/17 职场文书
小学作文评语大全
2014/04/21 职场文书
2014年端午节演讲稿范文
2014/05/23 职场文书
教师党员学习群众路线心得体会
2014/11/04 职场文书
2014年护理部工作总结
2014/11/14 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
幼儿园园长安全责任书
2015/05/08 职场文书
Python编程super应用场景及示例解析
2021/10/05 Python
volatile保证可见性及重排序方法
2022/08/05 Java/Android