当前位置: 首页 > 工具软件 > Qmgo > 使用案例 >

Qmgo使用教程及常用用法整理

夏景同
2023-12-01

安装

go get github.com/qiniu/qmgo

使用

创建连接

import (
	"context"
	"errors"
	"fmt"
	"github.com/qiniu/qmgo"
	"github.com/qiniu/qmgo/options"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/event"
	mgoptions "go.mongodb.org/mongo-driver/mongo/options"
	"gorm.io/gorm"
	"log"
	"strings"
	"sync"

	"time"
)
const (
	Ip         = "127.0.0.1"
	Port       = "27017"
	UserName   = "test"
	Password   = "123456789"
	DBName     = "test"
	AuthSource = "test"
)

var(
	ConnectTimeoutMS = int64(1000)
	MaxPoolSize = uint64(100)
	MinPoolSize = uint64(0)
)

ctx := context.Background()
// 拼接MongoDB Url
var mongoUrl string
if Password != "" {
    mongoUrl = "mongodb://" + UserName + ":" + Password + "@" +
    Ip + ":" + Port + "/" + DBName +
    "?authSource=" + AuthSource
} else {
    mongoUrl = "mongodb://" + Ip + ":" + Port
}

// 创建cmdMonitor,用于打印SQL
//startedCommands := make(map[int64]bson.Raw)
startedCommands := sync.Map{} // map[int64]bson.Raw
cmdMonitor := &event.CommandMonitor{
    Started: func(_ context.Context, evt *event.CommandStartedEvent) {
        startedCommands.Store(evt.RequestID, evt.Command)
        //startedCommands[evt.RequestID] = evt.Command
    },
    Succeeded: func(_ context.Context, evt *event.CommandSucceededEvent) {
        //log.Printf("Command: %v Reply: %v\n",
        //	startedCommands[evt.RequestID],
        //	evt.Reply,
        //)
        var commands bson.Raw
        v, ok := startedCommands.Load(evt.RequestID)
        if ok {
            commands = v.(bson.Raw)
        }
        log.Printf("\n【MongoDB】[%.3fms] [%v] %v \n", float64(evt.DurationNanos)/1e6, commands, evt.Reply)
    },
    Failed: func(_ context.Context, evt *event.CommandFailedEvent) {
        //log.Printf("Command: %v Failure: %v\n",
        //	startedCommands[evt.RequestID],
        //	evt.Failure,
        //)
        var commands bson.Raw
        v, ok := startedCommands.Load(evt.RequestID)
        if ok {
            commands = v.(bson.Raw)
        }
        log.Printf("\n【MongoDB】[%.3fms] [%v] \n %v \n", float64(evt.DurationNanos)/1e6, commands, evt.Failure)
    },
}
// 创建options
ops := options.ClientOptions{ClientOptions: &mgoptions.ClientOptions{}}
ops.SetMonitor(cmdMonitor)

// 创建一个数据库链接
client, err := qmgo.NewClient(ctx, &qmgo.Config{
    Uri:              mongoUrl,
    ConnectTimeoutMS: &ConnectTimeoutMS,
    MaxPoolSize:      &MaxPoolSize,
    MinPoolSize:      &MinPoolSize,
}, ops)


if err != nil {
    err = errors.New("MongoDB连接异常:" + err.Error())
    return
}
// 选择数据库
db := client.Database(DBName)
// 在初始化成功后,请defer来关闭连接
defer func() {
    if err = client.Close(ctx); err != nil {
        panic(err)
    }
}()

数据库

选择数据库

// 选择数据库
db := client.Database("dbname")

创建数据库

删除数据库

集合

选择集合

// 选中集合
coll := db.Collection("user1")

创建集合

// 创建集合
err = db.CreateCollection(ctx, "coll1")

删除集合

// 删除集合
err = coll.DropCollection(ctx)

获取当前集合列表

// 定义用于接收数据的结构体
type ListCollections struct {
	Cursor struct {
		FirstBatch []struct {
			Name string `json:"name"`
		} `json:"firstBatch"`
	} `json:"cursor"`
}

// 使用Command获取集合列表
result := db.RunCommand(ctx, bson.D{{"listCollections", 1}})
if result.Err() != nil {
   err = result.Err()
    return
}

var listColl ListCollections
// 将数据反序列化
err = result.Decode(&listColl)
if err != nil {
	return
}
// 遍历打印
for _, batch := range listColl.Cursor.FirstBatch {
    fmt.Println(batch.Name)
}

文档

定义模型

type UserInfo struct {
	Name       string    `bson:"name"`
	Age        uint16    `bson:"age"`
	Weight     uint32    `bson:"weight"`
	ExpireDate time.Time `bson:"expire_date"` // TTL索引对应的字段必须是date类型
}

插入文档

插入一条

// 插入一个文档
result, err := coll.InsertOne(ctx, userInfo)
if err != nil {
    log.Fatalln(err)
}
fmt.Println(result.InsertedID)

插入多条

// 创建数据
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 := coll.InsertMany(ctx, userInfos)
if err != nil {
    log.Fatalln(err)
}
fmt.Println(result.InsertedIDs)

更新文档

更新一条

// 查询条件
filter := bson.M{
    "name": "d4",
}
// 更新字段
update := bson.M{
    "$set": bson.M{"age": 7},
}
// 更新一条
err = coll.UpdateOne(ctx, filter, update)

更新多条

// 查询条件
filter := bson.M{
    "name": "d4",
}
// 更新字段
update := bson.M{
    "$set": bson.M{"age": 7},
}
// 更新多条
result,err := coll.UpdateAll(ctx, filter, update)

删除文档

删除字段

// 查询条件
filter := bson.M{
    "name": "d4",
}
// 删除字段字段
update := bson.M{
    "$unset": bson.M{"age": ""},
}
// 更新多条
result,err := coll.UpdateAll(ctx, filter, update)

删除一条

// 查询条件
filter := bson.M{
    "name": "a1",
}
// 删除一条
err = coll.Remove(ctx, filter)

会查询到匹配数据会报如下异常:
panic: mongo: no documents in result

删除多条

// 查询条件
filter := bson.M{
    "name": "a1",
}
// 删除多条
_,err = coll.RemoveAll(ctx, filter)

查询文档

查询一条

// 一定要初始化,否则报错,网上很多文章都没有做这一步
var findOptions = &options.FindOptions{}
// 查询一个文档
one := UserInfo{}
err = coll.Find(ctx, findOptions).One(&one)

查询多条

// 一定要初始化,否则报错,网上很多文章都没有做这一步
var findOptions = &options.FindOptions{}
// 查询所有文档
var users []UserInfo
err = coll.Find(ctx, findOptions).All(&users)

分页查询

// 页码
page := int64(1)
// 每页大小
pageSize := int64(10)
// 查询数据
err = coll.Find(ctx, findOptions).Skip((page-1) * pageSize).Limit(pageSize).All(users)

排序

// 正序
err = coll.Find(ctx, findOptions).Sort("weight").All(&users)
// 逆序
err = coll.Find(ctx, findOptions).Sort("-weight").All(&users)
// 组合排序
err = coll.Find(ctx, findOptions).Sort("age","-weight").All(&users)

Count

// 统计数据总量
count, err = db.Find(ctx, findOptions).Count()

OR

// 查询条件
filter := bson.M{
    "$or": bson.A{
        bson.M{"age": 5},
        bson.M{"age": 6},
        bson.M{"age": 7},
    },
}
// 查询所有数据
err = coll.Find(ctx, filter).All(&ones)

IN

// 查询条件
filter := bson.M{
    "age": bson.M{
        "$in": bson.A{5, 6, 7},
    },
}
// 查询所有数据
err = coll.Find(ctx, filter).All(&ones)

NOT IN

// 查询条件
filter := bson.M{
    "age": bson.M{
        "$nin": bson.A{5, 6, 7},
    },
}
// 查询所有数据
err = coll.Find(ctx, filter).All(&ones)

大于,大于等于,小于,小于等于,不等于

// 查询条件
filter := bson.M{
    "age": bson.M{
        "$gt":  5,  // 大于
        "$gte": 5,  // 大于等于
        "$lt":  10, // 小于
        "$lte": 10, // 小于等于
        "$ne":  5,  // 不等于
    },
}
// 查询所有数据
err = coll.Find(ctx, filter).All(&ones)

LIKE

// 需要模糊查询的内容
value := "xm"
// 查询条件
filter := bson.M{
    "name": primitive.Regex{
        Pattern: value,
        Options: "",
    },
}
// 查询所有数据
err = coll.Find(ctx, filter).All(&ones)

DISTINCT

var names []string
// 查询条件
var findOptions = &options.FindOptions{}
// DISTINCT
err = coll.Find(ctx, findOptions).Distinct("name", &names)

GROUP

// 查询结果
var showsWithInfo []bson.M
// 过滤条件
matchStage := bson.D{{
    "$match", []bson.E{
        {
            "age", bson.D{{"$gt", 5}, {"$lte", 6}}, // 5 < age <= 6
        },
        {
            "name", "a1", // name = a1
        },
    },
}}
// 分组条件
groupStage := bson.D{{
    "$group", bson.D{
        {
            "_id", bson.D{
                {"name", "$name"}, // 对name字段进行分组查询
                {"age", "$age"},   // 对age字段进行分组查询
            },
        },
        {
            "age_sum", bson.D{{"$sum", "$age"}}, // 计算总和
        },
        {
            "age_max", bson.D{{"$max", "$age"}}, // 计算最大值
        },
        {
            "age_min", bson.D{{"$min", "$age"}}, // 计算最小值
        },
        {
            "age_avg", bson.D{{"$avg", "$age"}}, // 计算平均值
        },
    },
}}
// 查询
err = coll.Aggregate(context.Background(), mongo.Pipeline{matchStage, groupStage}).All(&showsWithInfo)

索引

创建索引

TTL索引

指定x秒后过期

"github.com/qiniu/qmgo/options"
mgoptions "go.mongodb.org/mongo-driver/mongo/options"

// TTL索引
indexModel := options.IndexModel{
    Key:          []string{"expire_date"},
    IndexOptions: mgoptions.Index().SetExpireAfterSeconds(3600),
}
coll.CreateOneIndex(ctx, indexModel)

指定到具体的时间节点过期

"github.com/qiniu/qmgo/options"
mgoptions "go.mongodb.org/mongo-driver/mongo/options"

// TTL索引
indexModel := options.IndexModel{
    Key:          []string{"expire_date"},
    IndexOptions: mgoptions.Index().SetExpireAfterSeconds(0),
}
coll.CreateOneIndex(ctx, indexModel)
 类似资料: