Qmgo
English | 简体中文
Qmgo
is a MongoDB
driver
for Go
. It is based on MongoDB official driver, but easier to use like mgo (such as the chain call).
-
Qmgo
can allow user to use the new features ofMongoDB
in a more elegant way. -
Qmgo
is the first choice for migrating frommgo
to the newMongoDB driver
with minimal code changes.
Requirements
-Go 1.10
and above.
-MongoDB 2.6
and above.
Features
- CRUD to documents
- Sort、limit、count、select、distinct
- Transactions
- Hooks
- Predefine operator keys
- Aggregate、indexes operation、cursor
- All options when create connection, like: connection pool、pool monitor、auth、readPreference
Installation
- Use
go mod
to automatically install dependencies byimport github.com/qiniu/qmgo
Or
- Use
go get github.com/qiniu/qmgo
Usage
- Start
import
and 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")
If your connection points to a fixed database and collection, we recommend using the following more convenient way to initialize the connection.
All operations are based on cli
and no longer need to care about the database and collection.
cli, err := qmgo.Open(ctx, &qmgo.Config{Uri: "mongodb://localhost:27017", Database: "class", Coll: "user"})
The following examples will be based on cli
, if you use the first way for initialization, replace cli
with client
、db
or coll
After the initialization is successful, please defer
to close the connection
defer func() {
if err = cli.Close(ctx); err != nil {
panic(err)
}
}()
- Create index
Before doing the operation, we first initialize some data:
type UserInfo struct {
Name string `bson:"name"`
Age uint16 `bson:"age"`
Weight uint32 `bson:"weight"`
}
var userInfo = UserInfo{
Name: "xm",
Age: 7,
Weight: 40,
}
Create index
cli.EnsureIndexes(ctx, []string{}, []string{"age", "name,weight"})
- Insert a document
// insert one document
result, err := cli.Insert(ctx, userInfo)
- Find a document
// find one document
one := UserInfo{}
err = cli.Find(ctx, bson.M{"name": userInfo.Name}).One(&one)
- Delete documents
err = cli.Remove(ctx, bson.M{"age": 7})
- Insert multiple data
// multiple insert
var userInfos = []UserInfo{
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, userInfos)
- Search all, sort and limit
// 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()
- Update
// UpdateOne one
err := cli.UpdateOne(ctx, bson.M{"name": "d4"}, bson.M{"$set": bson.M{"age": 7}})
// UpdateAll
result, err := cli.UpdateAll(ctx, bson.M{"age": 6}, bson.M{"$set": bson.M{"age": 10}})
- Select
err := cli.Find(ctx, bson.M{"age": 10}).Select(bson.M{"age": 1}).One(&one)
- 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)
- Support All mongoDB Options when create connection
poolMonitor := &event.PoolMonitor{
Event: func(evt *event.PoolEvent) {
switch evt.Type {
case event.GetSucceeded:
fmt.Println("GetSucceeded")
case event.ConnectionReturned:
fmt.Println("ConnectionReturned")
}
},
}
opt := options.Client().SetPoolMonitor(poolMonitor) // more options use the chain options.
cli, err := Open(ctx, &Config{Uri: URI, Database: DATABASE, Coll: COLL}, opt)
- Transactions
The super simple and powerful transaction, with features like timeout
、retry
:
callback := func(sessCtx context.Context) (interface{}, error) {
// Important: make sure the sessCtx used in every operation in the whole transaction
if _, err := cli.InsertOne(sessCtx, bson.D{{"abc", int32(1)}}); err != nil {
return nil, err
}
if _, err := cli.InsertOne(sessCtx, bson.D{{"xyz", int32(999)}}); err != nil {
return nil, err
}
return nil, nil
}
result, err = cli.DoTransaction(ctx, callback)
- Predefine operator keys
// aggregate
matchStage := bson.D{{operator.Match, []bson.E{{"weight", bson.D{{operator.Gt, 30}}}}}}
groupStage := bson.D{{operator.Group, bson.D{{"_id", "$name"}, {"total", bson.D{{operator.Sum, "$age"}}}}}}
var showsWithInfo []bson.M
err = cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage}).All(&showsWithInfo)
- Hooks
Qmgo flexible hooks:
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
}
func (u *User) BeforeInsert() error {
fmt.Println("before insert called")
return nil
}
func (u *User) AfterInsert() error {
fmt.Println("before insert called")
return nil
}
u := &User{Name: "Alice", Age: 7}
_, err := cli.InsertOne(context.Background(), u, options.InsertOneOptions{
InsertHook: u,
})
Qmgo
vs go.mongodb.org/mongo-driver
Below we give an example of multi-file search、sort and limit to illustrate the similarities between qmgo
and mgo
and the improvement compare to go.mongodb.org/mongo-driver
.
How do we do ingo.mongodb.org/mongo-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)
How do we do in Qmgo
and mgo
:
// 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)
Qmgo
vs mgo
Differences between qmgo and mgo
Who is using
If you are using qmgo, please feel free to add your project name or repository here!
- Qiniu QCDN management system
- Qiniu RTC quality monitoring system
- Jesselivermore huanshoulv stock real-time quotes system
Contributing
The Qmgo project welcomes all contributors. We appreciate your help!