Qmgo

Recently, Quniu CDN RESEARCH and development team has opened source the MongoDB driver of qMGO-Go language. It is based on the official Driver of Mongo, but has better usability. The design refers to the old driver Mgo (such as the chain call of Mgo).

background

The original intention of doing Qmgo comes from the common trouble of gopher who use MongoDB. Before the official MongoDB Go driver took shape (V1.0.0 was released in March 2019), Mgo had been the dominant player, and its excellent interface design made it very popular. As one of the earliest companies to use Go, Qiniu is also a deep user of Mgo.

However, Mgo was no longer maintained three years ago, bugs are not fixed, new MongoDB features are not supported, and the interface design of the official driver is notoriously difficult to use.

In this context, Qmgo was born based on meeting the following requirements

  • Want new MongoDB features
  • Want a more stable driver
  • Want excellent interface design for Mgo
  • Migrating from Mgo to Qmgo requires minimal code change

Below, a brief introduction to the characteristics of Qmgo, details can be viewed by clicking: Qmgo

Where is it useful?

Use an example of multi-file lookup, sort, and limit to illustrate qmgo’s similarities to MGO and improvements to go.mongodb.org/mongo-driver

The official Driver needs to do this

// 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)
Copy the code

Qmgo and MGO are simpler and implement similar:

// 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)
Copy the code

Currently supported functions

  • Add, delete, change and check documents
  • The index configuration
  • Sort,Limit,Count,Select
  • Cursor
  • The aggregationAggregate

Method of use

  • To start,importAnd create a new connection
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")
      
Copy the code

If your connection is to a fixed database and collection, we recommend using the following convenient method to initialize the connection, and all subsequent operations are cli based without worrying about database and collection

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

The rest will be based oncliFor example, if you use the first traditional way of initialization, depending on the context, willclireplaceclient,dbcollCan be

After successful initialization, please defer to close the connection

defer func(a) {
    iferr = cli.Close(ctx); err ! =nil {
        panic(err)
    }
}()
Copy the code
  • Create indexes

To do this, let’s initialize some data:


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

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

Create indexes

cli.EnsureIndexes(ctx, []string[] {},string{"age"."name,weight"})
Copy the code
  • Insert a document
// insert one document
result, err := cli.Insert(ctx, oneUserInfo)
Copy the code
  • Finding a document
	// find one document
one := UserInfo{}
err = cli.Find(ctx, bson.M{"name": oneUserInfo.Name}).One(&one)
Copy the code
  • Delete the document
err = cli.Remove(ctx, bson.M{"age": 7})
Copy the code
  • Insert multiple data
// 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)
Copy the code
  • Batch search,SortandLimit
// find all 、sort and limit
batch := []UserInfo{}
cli.Find(ctx, bson.M{"age": 6}).Sort("weight").Limit(7).All(&batch)
Copy the code
  • Count
count, err := cli.Find(ctx, bson.M{"age": 6}).Count()
Copy the code
  • 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)
Copy the code

Welcome your attention and contribution, we will respond as soon as possible