Skip to content

mongo 组件 ​

基于 mongo-driver 管理多组 MongoDB 数据实例,配置方式与 gorm 组件 保持一致。

安装 ​

bash
go get github.com/cherry-game/components/mongo@latest

注册组件 ​

go
import (
	"github.com/cherry-game/cherry"
	cherryMongo "github.com/cherry-game/components/mongo"
)

func main() {
	app := cherry.Configure("./config/profile.json", "log-1", false, cherry.Standalone)

	app.Register(cherryMongo.NewComponent())
	app.Startup()
}

配置 ​

和 gorm 一样需要两处配合:mongo 段定义连接,节点 __settings__.mongo_id_list 声明要用哪些库。

json
{
    "node": {
        "game": [
            {
                "node_id": "game-1",
                "__settings__": {
                    "mongo_id_list": {
                        "log_db_id": "log_db_1"
                    }
                }
            }
        ]
    },

    "mongo": {
        "log_db_group": [
            {
                "enable": true,
                "db_id": "log_db_1",
                "db_name": "logs",
                "uri": "mongodb://127.0.0.1:27017",
                "timeout": 3
            }
        ]
    }
}

mongo.<group>[n] 字段 ​

字段类型默认值说明
db_idstring—逻辑库 id,必填,与 mongo_id_list 的值匹配
enablebooltrue为 false 时跳过该连接
db_namestring—库名
uristring—连接串,如 mongodb://127.0.0.1:27017
timeoutint3超时秒数,只有大于 3 才生效

timeout 大于 3 才生效

实现里判断的是 timeout > 3秒,否则使用默认的 3 秒。也就是说填 1 或 3 都等于 3 秒,想调成 5 秒才需要显式配置。

日志已脱敏

连接日志只打印库名和主机列表,不会输出完整的 uri,避免把账号密码写进日志。

使用数据库 ​

go
// 1. 取组件
mongoComponent, ok := app.Find(cherryMongo.Name).(*cherryMongo.Component)
if !ok || mongoComponent == nil {
	clog.Panicf("[component = %s] not found.", cherryMongo.Name)
}

// 2. 读逻辑库 id
logDbID := app.Settings().GetConfig("mongo_id_list").GetString("log_db_id")

// 3. 取 *mongo.Database
db := mongoComponent.GetDb(logDbID)

// 4. 正常使用 mongo-driver
collection := db.Collection("player_log")

新增或更新一条记录:

go
type Student struct {
	ID   int64  `bson:"id"`
	Name string `bson:"name"`
}

collection := db.Collection("numbers")

// 建唯一索引
_, err := collection.Indexes().CreateOne(context.TODO(), mongo.IndexModel{
	Keys:    bson.D{{Key: "id", Value: 1}},
	Options: options.Index().SetUnique(true),
})

// upsert
filter := bson.D{{Key: "id", Value: student.ID}}
update := bson.D{{Key: "$set", Value: student}}
_, err = collection.FindOneAndUpdate(context.TODO(), filter, update,
	options.FindOneAndUpdate().SetUpsert(true),
)

驱动是 v2

组件用的是 go.mongodb.org/mongo-driver/v2,import 路径带 /v2:

go
import (
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

从 v1 升级时注意:mongo.Connect(opts) 不再接收 ctx,且 primitive 系列类型已移除(应改用 bson 里的对应类型)。模型字段的 tag 仍然是 bson:"..."。

API ​

方法说明
NewComponent() *Component创建组件
CreateDatabase(uri, dbName string, timeout ...time.Duration) (*mongo.Database, error)直接建连接,可脱离组件单独使用
GetDb(id string) *mongo.Database按逻辑库 id 取连接
GetHashDb(groupID string, hashFn HashDb) (*mongo.Database, bool)在一组库里按哈希规则选一个
GetDbMap(groupID string) (map[string]*mongo.Database, bool)取整组的连接表

CreateDatabase 是导出的,单元测试或临时脚本里可以直接用,不必注册组件:

go
mdb, err := cherryMongo.CreateDatabase("mongodb://localhost:27017", "test")
collection := mdb.Collection("numbers")

可运行示例见 mongo_test.go。