Convert Figma logo to code with AI

qiniu logoqmgo

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

1,302
152
1,302
48

Top Related Projects

1,972

The MongoDB driver for Go

The Official Golang driver for MongoDB

16,124

general purpose extensions to golang's database/sql

36,742

The fantastic ORM library for Golang, aims to be developer friendly

Quick Overview

Qmgo is a MongoDB driver for Go that provides a simple and efficient way to interact with MongoDB databases. It is designed to be a lightweight and easy-to-use alternative to the official MongoDB Go driver, with a focus on providing a more intuitive and developer-friendly API.

Pros

  • Simple and Intuitive API: Qmgo offers a straightforward and easy-to-use API, making it accessible for developers who are new to MongoDB or Go.
  • Performance Optimization: The library is designed to be efficient and performant, with features like automatic connection pooling and connection management.
  • Compatibility with the Official MongoDB Go Driver: Qmgo is compatible with the official MongoDB Go driver, allowing developers to easily migrate existing projects.
  • Extensive Documentation and Community Support: The project has comprehensive documentation and a growing community of contributors and users.

Cons

  • Limited Functionality: Compared to the official MongoDB Go driver, Qmgo may have a more limited set of features and functionality.
  • Potential Compatibility Issues: As a third-party library, Qmgo may not always be in sync with the latest updates and changes in the official MongoDB Go driver.
  • Smaller Community: While the Qmgo community is growing, it may not have the same level of support and resources as the official MongoDB Go driver.
  • Lack of Advanced Features: Qmgo may not provide the same level of advanced features and customization options as the official MongoDB Go driver.

Code Examples

Here are a few code examples demonstrating the usage of Qmgo:

Connecting to a MongoDB Database

import (
    "context"
    "fmt"

    "github.com/qiniu/qmgo"
)

func main() {
    ctx := context.Background()
    client, err := qmgo.NewClient(ctx, &qmgo.Config{
        Uri:      "mongodb://localhost:27017",
        Database: "test",
    })
    if err != nil {
        fmt.Println("connect to mongodb error:", err)
        return
    }
    defer client.Close(ctx)

    // Use the client to interact with the MongoDB database
    // ...
}

Inserting a Document

type Person struct {
    Name string `bson:"name"`
    Age  int    `bson:"age"`
}

func main() {
    ctx := context.Background()
    client, _ := qmgo.NewClient(ctx, &qmgo.Config{
        Uri:      "mongodb://localhost:27017",
        Database: "test",
    })
    defer client.Close(ctx)

    coll := client.Database("test").Collection("persons")
    person := Person{
        Name: "John Doe",
        Age:  30,
    }
    _, err := coll.InsertOne(ctx, person)
    if err != nil {
        fmt.Println("insert error:", err)
        return
    }
}

Querying Documents

func main() {
    ctx := context.Background()
    client, _ := qmgo.NewClient(ctx, &qmgo.Config{
        Uri:      "mongodb://localhost:27017",
        Database: "test",
    })
    defer client.Close(ctx)

    coll := client.Database("test").Collection("persons")
    filter := bson.M{"age": bson.M{"$gt": 25}}
    var persons []Person
    err := coll.Find(ctx, filter).All(&persons)
    if err != nil {
        fmt.Println("query error:", err)
        return
    }

    for _, p := range persons {
        fmt.Println(p)
    }
}

Getting Started

To get started with Qmgo, follow these steps:

  1. Install the Qmgo package:
go get github.com/qiniu/qmgo
  1. Import the Qmgo package in your Go code:
import "github.com/qiniu/qmgo"
  1. Create a new Qmgo client and connect to a MongoDB database:
ctx := context.Background()

Competitor Comparisons

1,972

The MongoDB driver for Go

Pros of mgo

  • More established and widely used in the Go community
  • Extensive documentation and community support
  • Supports a broader range of MongoDB versions

Cons of mgo

  • No longer actively maintained (last commit in 2018)
  • Lacks support for newer MongoDB features and optimizations
  • May have compatibility issues with recent Go versions

Code Comparison

mgo:

session, err := mgo.Dial("mongodb://localhost")
if err != nil {
    panic(err)
}
defer session.Close()

c := session.DB("test").C("users")
err = c.Insert(bson.M{"name": "John", "age": 30})

qmgo:

ctx := context.Background()
client, err := qmgo.NewClient(ctx, &qmgo.Config{Uri: "mongodb://localhost"})
if err != nil {
    panic(err)
}
defer client.Close(ctx)

coll := client.Database("test").Collection("users")
_, err = coll.InsertOne(ctx, bson.M{"name": "John", "age": 30})

The main differences in the code are:

  1. qmgo uses a context-based API
  2. qmgo's client creation is more streamlined
  3. mgo uses Insert, while qmgo uses InsertOne
  4. qmgo's API is more aligned with the official MongoDB Go driver

Overall, qmgo offers a more modern and actively maintained alternative to mgo, with better support for recent MongoDB features and Go practices.

The Official Golang driver for MongoDB

Pros of mongo-go-driver

  • Official MongoDB driver with comprehensive feature support
  • Extensive documentation and community support
  • More frequent updates and maintenance

Cons of mongo-go-driver

  • Steeper learning curve for beginners
  • More verbose API, requiring more code for common operations

Code Comparison

mongo-go-driver:

client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017"))
collection := client.Database("testdb").Collection("users")
result, err := collection.InsertOne(context.TODO(), bson.D{{"name", "John"}, {"age", 30}})

qmgo:

cli, err := qmgo.NewClient(context.Background(), &qmgo.Config{Uri: "mongodb://localhost:27017"})
db := cli.Database("testdb")
coll := db.Collection("users")
_, err := coll.InsertOne(context.Background(), bson.M{"name": "John", "age": 30})

Summary

mongo-go-driver is the official MongoDB driver for Go, offering comprehensive features and extensive support. It's well-maintained but can be more complex for beginners. qmgo, on the other hand, provides a simpler API inspired by the MongoDB shell, making it easier to use for common operations. However, it may lack some advanced features and has a smaller community compared to the official driver.

16,124

general purpose extensions to golang's database/sql

Pros of sqlx

  • Supports multiple database types (MySQL, PostgreSQL, SQLite)
  • Provides a more SQL-centric approach, allowing direct use of SQL queries
  • Offers a lightweight and flexible API for database operations

Cons of sqlx

  • Lacks built-in ODM (Object-Document Mapping) features
  • Requires more manual handling of database operations compared to Qmgo
  • May require more boilerplate code for complex queries and operations

Code Comparison

sqlx:

db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
rows, err := db.Queryx("SELECT * FROM users WHERE id = $1", id)
var user User
err = rows.StructScan(&user)

Qmgo:

cli, err := qmgo.NewClient(context.Background(), &qmgo.Config{Uri: "mongodb://localhost:27017"})
db := cli.Database("example")
coll := db.Collection("user")
err = coll.Find(context.Background(), bson.M{"name": "user1"}).One(&user)

Summary

sqlx is a versatile SQL library supporting multiple databases, offering a SQL-centric approach with a lightweight API. It provides more flexibility but requires more manual handling of database operations. Qmgo, on the other hand, is specifically designed for MongoDB, offering built-in ODM features and a more streamlined API for document-based operations. The choice between the two depends on the specific database requirements and development preferences of the project.

36,742

The fantastic ORM library for Golang, aims to be developer friendly

Pros of gorm

  • More mature and widely adopted ORM for Go, with a larger community and ecosystem
  • Supports multiple databases (MySQL, PostgreSQL, SQLite, etc.) out of the box
  • Offers advanced features like associations, hooks, and migrations

Cons of gorm

  • Steeper learning curve due to its extensive feature set
  • Can be slower for simple queries compared to raw SQL or lighter ORMs
  • May introduce overhead for applications with simple database needs

Code Comparison

qmgo:

cli, err := qmgo.NewClient(ctx, &qmgo.Config{Uri: "mongodb://localhost:27017"})
db := cli.Database("test")
coll := db.Collection("user")

err := coll.InsertOne(ctx, User{Name: "Alice", Age: 30})

gorm:

db, err := gorm.Open(mysql.Open("user:password@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})

user := User{Name: "Alice", Age: 30}
result := db.Create(&user)

Summary

qmgo is a MongoDB-specific driver for Go, offering a simpler API for MongoDB operations. gorm, on the other hand, is a full-featured ORM supporting multiple databases. While gorm provides more flexibility and features, qmgo may be more suitable for projects exclusively using MongoDB and requiring a lightweight solution.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Qmgo

Build Status Coverage Status Go Report Card GitHub release GoDoc

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).

  • Qmgo allows users 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, 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 mod to automatically install dependencies by import 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, 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, replace cli with client、db or coll

    Make 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)
    

    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(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)
    

    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 createAt、updateAt and _id in 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 update
    

    Check examples here

    More about automatically fields

  • 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、ReplaceOne

  • Plugin

    • 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 Do

      Qmgo will call Do before and after the operation

    middleware.Register(Do)
    

    Example

    The hook、automatically fields and validation tags in 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: