Skip to content

develop1024/qmgo

 
 

Repository files navigation

Qmgo

Build Status Coverage Status Go Report Card GitHub release GoDoc

简体中文

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 of MongoDB in a more elegant way.

  • Qmgo is the first choice for migrating from mgo to the new MongoDB driver with minimal code changes.

Requirements

-Go 1.10 and above.

-MongoDB 2.6 and above.

Features

  • CRUD to documents
  • Configuration when create connection:connection pool、pool Monitor、Auth、ReadPreference
  • Create indexes
  • Sort、limit、count、select
  • Cursor
  • Aggregate
  • Transactions

Installation

The recommended way is to use go mod to automatically install dependencies by import github.com/qiniu/qmgo and build .

Of course, the following methods are also feasible:

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 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 oneUserInfo = 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, oneUserInfo)
  • Find a document
// find one document
  one := UserInfo{}
  err = cli.Find(ctx, bson.M{"name": oneUserInfo.Name}).One(&one)
  • Delete documents
err = cli.Remove(ctx, bson.M{"age": 7})
  • 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)
  • 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)
  • Pool Monitor
poolMonitor := &event.PoolMonitor{
	Event: func(evt *event.PoolEvent) {
		switch evt.Type {
		case event.GetSucceeded:
			fmt.Println("GetSucceeded")
		case event.ConnectionReturned:
			fmt.Println("ConnectionReturned")
		}
	},
}
cli, err := Open(ctx, &Config{Uri: URI, Database: DATABASE, Coll: COLL, PoolMonitor: poolMonitor})
  • 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

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!

Join qmgo wechat group:

avatar

About

Qmgo - The MongoDB driver for Go . It‘s based on official mongo-go-driver but easier to use like Mgo.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 100.0%