Skip to content
jiangz222 edited this page Sep 13, 2020 · 7 revisions

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 clientdb 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 timeoutretry:

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)

More about transaction

  • 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("after insert called")
  	return nil
}

u := &User{Name: "Alice", Age: 7}
_, err := cli.InsertOne(context.Background(), u, options.InsertOneOptions{
  InsertHook: u,
})

More about hooks

  • Automatically fields

    Qmgo support two ways to make specific fields automatically update in specific API

    • Default fields

    Inject field.DefaultField in document struct, Qmgo will update createAtupdateAt and _id in update and insert operation.

       type User struct {
        field.DefaultField `bson:",inline"`
       
        Name string `bson:"name"`
        Age  int    `bson:"age"`
       }
    • Custom fields

    Define the custom fields associated with createAtupdateAt and _id, Qmgo will update them in update and insert operation.

    type User struct {
        Name string `bson:"name"`
        Age  int    `bson:"age"`
    
        MyId         string    `bson:"myId"`
        CreateTimeAt time.Time `bson:"createTimeAt"`
        UpdateTimeAt int64     `bson:"updateTimeAt"`
    }
    // Define the custom fields
    func (u *User) CustomFields() field.CustomFieldsBuilder {
        return field.NewCustom().SetCreateAt("CreateTimeAt").SetUpdateAt("UpdateTimeAt").SetId("MyId")
    }

examples here

More about automatically fields