qiniu/qmgo
qiniu/qmgo has 1,355 GitHub stars and 151 forks. GitHot measured +1 in 7 days. Last checked 2026-11-09 05:39 UTC. Last push 2026-06-20.
Qmgo - The Go driver for MongoDB. It‘s based on official mongo-go-driver but easier to use like Mgo.
What you can do
- CRUD to documents, with all official supported options
- Sort、limit、count、select、distinct
- Automatically default and custom fields
- Predefine operator keys
측정된 스타 증가
- in 24h
- 업데이트 지연
- in 7 days
- +1
- in 15 days
- 업데이트 지연
- in 1 month
- 업데이트 지연
서로 겹치는 기간의 순증가량이며 일별 합계가 아닙니다. 측정값이 없으면 비워 둡니다. 스타는 관심도를 나타내며 품질을 보장하지 않습니다.
README.md
OriginalQmgo
English | 简体中文
Qmgo is a Go driver for MongoDB . It is based on MongoDB official driver, but easier to use like mgo (such as the chain call).
Qmgoallows users to use the new features ofMongoDBin a more elegant way.Qmgois the first choice for migrating frommgoto the newMongoDB driverwith minimal code changes.
Requirements
-Go 1.10 and above.
-MongoDB 2.6 and above.
Features
- CRUD to documents, with all official supported options
- Sort、limit、count、select、distinct
- Transactions
- Hooks
- Automatically default and custom fields
- Predefine operator keys
- Aggregate、indexes operation、cursor
- Validation tags
- Plugin
Installation
- Use
go modto automatically install dependencies byimport github.com/qiniu/qmgo
Or
- Use
go get github.com/qiniu/qmgo
Usage
Start
importand create a new connectionimport ( "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, recommend using the following way to initialize the connection. All operations can be based on
cli: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, replacecliwithclient、dborcollMake sure to defer a call to Disconnect after instantiating your client:
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.CreateOneIndex(context.Background(), options.IndexModel{Key: []string{"name"}}) cli.CreateIndexes(context.Background(), []options.IndexModel{{Key: []string{"id2", "id3"}}})Insert a document
// insert one document result, err := cli.InsertOne(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(ctx context.Context) error { fmt.Println("before insert called") return nil } func (u *User) AfterInsert(ctx context.Context) error { fmt.Println("after insert called") return nil } u := &User{Name: "Alice", Age: 7} _, err := cli.InsertOne(context.Background(), u)Automatically fields
Qmgo support two ways to make specific fields automatically update in specific API
- Default fields
Inject
field.DefaultFieldin document struct, Qmgo will updatecreateAt、updateAtand_idin update and insert operation.type User struct { field.DefaultField `bson:",inline"` Name string `bson:"name"` Age int `bson:"age"` } u := &User{Name: "Lucas", Age: 7} _, err := cli.InsertOne(context.Background(), u) // Fields with tag createAt、updateAt and _id will be generated automatically- Custom fields
Define the custom fields, 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") } u := &User{Name: "Lucas", Age: 7} _, err := cli.InsertOne(context.Background(), u) // CreateTimeAt、UpdateTimeAt and MyId will be generated automatically // suppose Id and ui is ready err = cli.ReplaceOne(context.Background(), bson.M{"_id": Id}, &ui) // UpdateTimeAt will updateCheck examples here
Validation tags
Qmgo Validation tags is Based on go-playground/validator.
So Qmgo support all validations on structs in go-playground/validator, such as:
type User struct { FirstName string `bson:"fname"` LastName string `bson:"lname"` Age uint8 `bson:"age" validate:"gte=0,lte=130" ` // Age must in [0,130] Email string `bson:"e-mail" validate:"required,email"` // Email can't be empty string, and must has email format CreateAt time.Time `bson:"createAt" validate:"lte"` // CreateAt must lte than current time Relations map[string]string `bson:"relations" validate:"max=2"` // Relations can't has more than 2 elements }Qmgo tags only supported in following API:
InsertOne、InsertyMany、Upsert、UpsertId、ReplaceOnePlugin
- Implement following method:
func Do(ctx context.Context, doc interface{}, opType operator.OpType, opts ...interface{}) error{ // do anything }Call Register() in package middleware, register the method
DoQmgo will call
Dobefore and after the operation
middleware.Register(Do)The
hook、automatically fieldsandvalidation tagsin Qmgo run on plugin.
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
Contributing
The Qmgo project welcomes all contributors. We appreciate your help!
Communication:
- Join qmgo discussions
관련 프로젝트 살펴보기
Asabeneh/30-Days-Of-Python
30 Days of Python 프로그래밍 챌린지는 Python 프로그래밍 언어를 30일 동안 배우기 위한 단계별 가이드입니다. 이 챌린지는 100일 이상 걸릴 수 있습니다. 자신의 속도에 맞춰 진행하세요. 다음 동영상도 도움이 될 수 있습니다: https://www.youtube.com/channel/UC7PNRuno1rzYPb1xLa4yktw
78,486 스타grafana/grafana
개방적이고 조합 가능한 옵저버빌리티 및 데이터 시각화 플랫폼입니다. Prometheus, Loki, Elasticsearch, InfluxDB, Postgres 등 여러 소스의 메트릭, 로그, 트레이스를 시각화합니다.
77,790 스타redis/redis
실시간 데이터 기반 애플리케이션을 구축하는 개발자에게 Redis는 가장 선호되고, 가장 빠르며, 기능이 가장 풍부한 캐시, 데이터 구조 서버이자 문서 및 벡터 쿼리 엔진입니다.
77,332 스타apache/superset
Apache Superset는 데이터 시각화 및 데이터 탐색 플랫폼입니다.
75,455 스타