Qmgo - 更好用的Go语言MongoDB driver

jiangzhi · · 2379 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

## Qmgo 最近,七牛CDN研发团队开源了[Qmgo](https://github.com/qiniu/qmgo) - Go语言的MongoDB driver,它基于[Mongo官方driver](https://github.com/mongodb/mongo-go-driver)实现,但是有着更好的易用性,设计上参考了老牌的driver [Mgo](https://github.com/go-mgo/mgo) (比如Mgo的链式调用)。 ## 背景 做Qmgo的初衷,来自于使用MongoDB的gopher们共同的困扰,在MongoDB的Go官方driver成型前(v1.0.0发布在2019年3月),一直是Mgo一统江湖,出色的接口设计让其非常流行。七牛做为最早使用Go的公司之一,自然也是Mgo的深度用户。 但是Mgo已经在3年前不再维护,bug不修复,MongoDB的新特性自然也无法支持,而官方driver的接口设计是出名的不易用。 这样的背景下,基于满足下面的需求,Qmgo诞生了 - 想要MongoDB新特性 - 想要更稳定的driver - 想要Mgo出色的接口设计 - 想要从Mgo迁移到Qmgo,代码改动最小 下面,简单介绍一下Qmgo的特点,详情可以点击查看:[Qmgo](https://github.com/qiniu/qmgo) ## 好用在哪里? 举一个多文件查找、`sort`和`limit`的例子, 说明`qmgo`和`mgo`的相似,以及对`go.mongodb.org/mongo-driver`的改进 官方`Driver`需要这样实现 ```go // go.mongodb.org/mongo-driver // find all 、sort and limit findOptions := options.Find() findOptions.SetLimit(7) // set limit var sorts D sorts = append(sorts, E{Key: "weight", Value: 1}) findOptions.SetSort(sorts) // set sort batch := []UserInfo{} cur, err := coll.Find(ctx, bson.M{"age": 6}, findOptions) cur.All(ctx, &batch) ``` `Qmgo`和`mgo`更简单,而且实现相似: ```go // qmgo // find all 、sort and limit batch := []UserInfo{} cli.Find(ctx, bson.M{"age": 6}).Sort("weight").Limit(7).All(&batch) // mgo // find all 、sort and limit coll.Find(bson.M{"age": 6}).Sort("weight").Limit(7).All(&batch) ``` ## 当前支持的功能 - 文档的增删改查 - 索引配置 - `Sort`、`Limit`、`Count`、`Select` - `Cursor` - 聚合`Aggregate` ## 使用方法 - 开始,`import`并新建连接 ```go import( "context" "github.com/qiniu/qmgo" ) ctx := context.Background() client, err := qmgo.NewClient(ctx, &qmgo.Config{Uri: "mongodb://localhost:27017"}) db := client.Database("class") coll := db.Collection("user") ``` 如果你的连接是指向固定的database和collection,我们推荐使用下面的更方便的方法初始化连接,后续操作都基于`cli`而不用再关心database和collection ```go cli, err := qmgo.Open(ctx, &qmgo.Config{Uri: "mongodb://localhost:27017", Database: "class", Coll: "user"}) ``` ***后面都会基于`cli`来举例,如果你使用第一种传统的方式进行初始化,根据上下文,将`cli`替换成`client`、`db` 或 `coll`即可*** 在初始化成功后,请`defer`来关闭连接 ```go defer func() { if err = cli.Close(ctx); err != nil { panic(err) } }() ``` - 创建索引 做操作前,我们先初始化一些数据: ```go type UserInfo struct { Name string `bson:"name"` Age uint16 `bson:"age"` Weight uint32 `bson:"weight"` } var oneUserInfo = UserInfo{ Name: "xm", Age: 7, Weight: 40, } ``` 创建索引 ```go cli.EnsureIndexes(ctx, []string{}, []string{"age", "name,weight"}) ``` - 插入一个文档 ```go // insert one document result, err := cli.Insert(ctx, oneUserInfo) ``` - 查找一个文档 ```go // find one document one := UserInfo{} err = cli.Find(ctx, bson.M{"name": oneUserInfo.Name}).One(&one) ``` - 删除文档 ```go err = cli.Remove(ctx, bson.M{"age": 7}) ``` - 插入多条数据 ```go // multiple insert var batchUserInfoI = []interface{}{ UserInfo{Name: "a1", Age: 6, Weight: 20}, UserInfo{Name: "b2", Age: 6, Weight: 25}, UserInfo{Name: "c3", Age: 6, Weight: 30}, UserInfo{Name: "d4", Age: 6, Weight: 35}, UserInfo{Name: "a1", Age: 7, Weight: 40}, UserInfo{Name: "a1", Age: 8, Weight: 45}, } result, err = cli.Collection.InsertMany(ctx, batchUserInfoI) ``` - 批量查找、`Sort`和`Limit` ```go // find all 、sort and limit batch := []UserInfo{} cli.Find(ctx, bson.M{"age": 6}).Sort("weight").Limit(7).All(&batch) ``` - Count ````go count, err := cli.Find(ctx, bson.M{"age": 6}).Count() ```` - Aggregate ```go matchStage := bson.D{{"$match", []bson.E{{"weight", bson.D{{"$gt", 30}}}}}} groupStage := bson.D{{"$group", bson.D{{"_id", "$name"}, {"total", bson.D{{"$sum", "$age"}}}}}} var showsWithInfo []bson.M err = cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage}).All(&showsWithInfo) ``` ## 欢迎大家关注和贡献,我们会尽快积极响应

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2379 次点击  ∙  1 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传