Go 每日一库之 Qmgo - 更好用的 Go 语言 MongoDB driver

共 3626字,需浏览 8分钟

 ·

2020-08-12 02:06

点击上方蓝色“Go语言中文网”关注我们,领全套Go资料,每天学习 Go 语言

最近,七牛 CDN 研发团队开源了Qmgo[1] - Go 语言的 MongoDB driver,它基于Mongo 官方 driver[2]实现,但是有着更好的易用性,设计上参考了老牌的 driver Mgo[3] (比如 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[4]

好用在哪里?

举一个多文件查找、sortlimit的例子, 说明qmgomgo的相似,以及对go.mongodb.org/mongo-driver的改进

官方Driver需要这样实现

// 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)

Qmgomgo更简单,而且实现相似:

// 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)

当前支持的功能

  • 文档的增删改查
  • 索引配置
  • SortLimitCountSelect
  • Cursor
  • 聚合Aggregate

使用方法

  • 开始,import并新建连接
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

cli, err := qmgo.Open(ctx, &qmgo.Config{Uri: "mongodb://localhost:27017", Database: "class", Coll: "user"})

*后面都会基于cli来举例,如果你使用第一种传统的方式进行初始化,根据上下文,将cli替换成clientdbcoll即可*

在初始化成功后,请defer来关闭连接

defer func() {
    if err = cli.Close(ctx); err != nil {
        panic(err)
    }
}()
  • 创建索引

做操作前,我们先初始化一些数据:

type UserInfo struct {
    Name   string `bson:"name"`
    Age    uint16 `bson:"age"`
    Weight uint32 `bson:"weight"`
}

var oneUserInfo = UserInfo{
    Name:   "xm",
    Age:    7,
    Weight: 40,
}

创建索引

cli.EnsureIndexes(ctx, []string{}, []string{"age""name,weight"})
  • 插入一个文档
// insert one document
result, err := cli.Insert(ctx, oneUserInfo)
  • 查找一个文档
    // find one document
one := UserInfo{}
err = cli.Find(ctx, bson.M{"name": oneUserInfo.Name}).One(&one)
  • 删除文档
err = cli.Remove(ctx, bson.M{"age"7})
  • 插入多条数据
// 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)
  • 批量查找、SortLimit
// find all 、sort and limit
batch := []UserInfo{}
cli.Find(ctx, bson.M{"age"6}).Sort("weight").Limit(7).All(&batch)
  • Count
count, err := cli.Find(ctx, bson.M{"age"6}).Count()
  • Aggregate
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)

参考资料

[1]

Qmgo: https://github.com/qiniu/qmgo

[2]

Mongo官方driver: https://github.com/mongodb/mongo-go-driver

[3]

Mgo: https://github.com/go-mgo/mgo

[4]

Qmgo: https://github.com/qiniu/qmgo



推荐阅读


学习交流 Go 语言,扫码回复「进群」即可


站长 polarisxu

自己的原创文章

不限于 Go 技术

职场和创业经验


Go语言中文网

每天为你

分享 Go 知识

Go爱好者值得关注


浏览 87
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报