game_sync/tools/mongoctl/README-zh.md

484 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# mongoctl
### 1.介绍
mongoctl是一个自动化生成MongoDB数据访问对象Data Access Object的工具。
### 2.优势
* 支持primitive.ObjectID、primitive.DateTime类型的自动填充。
* 支持int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64类型的自增长。
* 提供了对数据库字段的统一生成方案,避免了业务代码中随处可见的数据库字段的问题。
* 提供了包括InsertOne、InsertMany、UpdateOne、UpdateOneByID、UpdateMany、FindOne、FindOneByID、FindMany、DeleteOne、DeleteOneByID、DeleteMany、Count、Aggregate等多种数据库操作接口。
* 提供了对数据库操作接口的扩展能力。
* 提供了分包与不分包两种包解决方案。
* 支持目录和文件名风格的自定义。
### 3.安装
```bash
go install
```
### 4.用法
```bash
用法 mongoctl:
mongoctl [flags] -model-dir=. -model-names=T,T -dao-dir=./dao
Flags:
-counter-name string
自增模型名称; 默认是 counter
-dao-dir string
生成代码所在目录; 必需
-dao-pkg-path string
生成代码所在目录的包名; 默认自动生成
-file-style string
代码文件名称风格; 选项: kebab | underscore | lower | camel | pascal; 默认是 underscore (default "underscore")
-model-dir string
模型所在目录; 必需
-model-names string
模型结构体名称; 必需
-model-pkg-alias string
模型包别名
-model-pkg-path string
模型包名; 默认自动生成
-sub-pkg-enable
每个模型创建一个子包; 默认关闭
-sub-pkg-style string
模型子包目录名称风格; 选项: kebab | underscore | lower | camel | pascal; 默认是 kebab (default "kebab")
```
### 5.标签
在模型定义中支持对gen标签的解析目前支持以下标签解析
| 标签名称 | | 示例 | 说明 |
| -------- | ---------------------------------------------------------- | ------------------ | -------------------------- |
| autoFill | primitive.ObjectID、primitive.DateTime | gen:"autoFill" | |
| autoIncr | int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64 | gen:"autoIncr:uid" | 该自增为原子操作,会在生成代码时同步生成计数器代码。 |
### 6.示例
###### 6-1.创建模型
model/mail.go
```go
package model
import "go.mongodb.org/mongo-driver/bson/primitive"
//go:generate mongoctl -model-dir=. -model-names=Mail -dao-dir=../dao/
type Mail struct {
ID primitive.ObjectID `bson:"_id" gen:"autoFill"` // 邮件ID
Title string `bson:"title"` // 邮件标题
Content string `bson:"content"` // 邮件内容
Sender int64 `bson:"sender"` // 邮件发送者
Receiver int64 `bson:"receiver"` // 邮件接受者
Status int `bson:"status"` // 邮件状态
SendTime primitive.DateTime `bson:"send_time" gen:"autoFill"` // 发送时间
}
```
###### 6-2.生成dao文件
```bash
go generate ./...
```
###### 6-3.生成的dao文件示例
dao/internal/mail.go
```go
// --------------------------------------------------------------------------------------------
// The following code is automatically generated by the mongo-dao-generator tool.
// Please do not modify this code manually to avoid being overwritten in the next generation.
// For more tool details, please click the link to view https://github.com/dobyte/mongo-dao-generator
// --------------------------------------------------------------------------------------------
package internal
import (
"context"
"errors"
models "github.com/dobyte/mongo-dao-generator/example/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
type MailFilterFunc func(cols *MailColumns) interface{}
type MailUpdateFunc func(cols *MailColumns) interface{}
type MailPipelineFunc func(cols *MailColumns) interface{}
type MailCountOptionsFunc func(cols *MailColumns) *options.CountOptions
type MailAggregateOptionsFunc func(cols *MailColumns) *options.AggregateOptions
type MailFindOneOptionsFunc func(cols *MailColumns) *options.FindOneOptions
type MailFindManyOptionsFunc func(cols *MailColumns) *options.FindOptions
type MailUpdateOptionsFunc func(cols *MailColumns) *options.UpdateOptions
type MailDeleteOptionsFunc func(cols *MailColumns) *options.DeleteOptions
type MailInsertOneOptionsFunc func(cols *MailColumns) *options.InsertOneOptions
type MailInsertManyOptionsFunc func(cols *MailColumns) *options.InsertManyOptions
type Mail struct {
Columns *MailColumns
Database *mongo.Database
Collection *mongo.Collection
}
type MailColumns struct {
ID string // 邮件ID
Title string // 邮件标题
Content string // 邮件内容
Sender string // 邮件发送者
Receiver string // 邮件接受者
Status string // 邮件状态
SendTime string // 发送时间
}
var mailColumns = &MailColumns{
ID: "_id", // 邮件ID
Title: "title", // 邮件标题
Content: "content", // 邮件内容
Sender: "sender", // 邮件发送者
Receiver: "receiver", // 邮件接受者
Status: "status", // 邮件状态
SendTime: "send_time", // 发送时间
}
func NewMail(db *mongo.Database) *Mail {
return &Mail{
Columns: mailColumns,
Database: db,
Collection: db.Collection("mail"),
}
}
// Count returns the number of documents in the collection.
func (dao *Mail) Count(ctx context.Context, filterFunc MailFilterFunc, optionsFunc ...MailCountOptionsFunc) (int64, error) {
var (
opts *options.CountOptions
filter = filterFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.CountDocuments(ctx, filter, opts)
}
// Aggregate executes an aggregate command against the collection and returns a cursor over the resulting documents.
func (dao *Mail) Aggregate(ctx context.Context, pipelineFunc MailPipelineFunc, optionsFunc ...MailAggregateOptionsFunc) (*mongo.Cursor, error) {
var (
opts *options.AggregateOptions
pipeline = pipelineFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.Aggregate(ctx, pipeline, opts)
}
// InsertOne executes an insert command to insert a single document into the collection.
func (dao *Mail) InsertOne(ctx context.Context, model *models.Mail, optionsFunc ...MailInsertOneOptionsFunc) (*mongo.InsertOneResult, error) {
if model == nil {
return nil, errors.New("model is nil")
}
if err := dao.autofill(ctx, model); err != nil {
return nil, err
}
var opts *options.InsertOneOptions
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.InsertOne(ctx, model, opts)
}
// InsertMany executes an insert command to insert multiple documents into the collection.
func (dao *Mail) InsertMany(ctx context.Context, models []*models.Mail, optionsFunc ...MailInsertManyOptionsFunc) (*mongo.InsertManyResult, error) {
if len(models) == 0 {
return nil, errors.New("models is empty")
}
documents := make([]interface{}, 0, len(models))
for i := range models {
model := models[i]
if err := dao.autofill(ctx, model); err != nil {
return nil, err
}
documents = append(documents, model)
}
var opts *options.InsertManyOptions
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.InsertMany(ctx, documents, opts)
}
// UpdateOne executes an update command to update at most one document in the collection.
func (dao *Mail) UpdateOne(ctx context.Context, filterFunc MailFilterFunc, updateFunc MailUpdateFunc, optionsFunc ...MailUpdateOptionsFunc) (*mongo.UpdateResult, error) {
var (
opts *options.UpdateOptions
filter = filterFunc(dao.Columns)
update = updateFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.UpdateOne(ctx, filter, update, opts)
}
// UpdateOneByID executes an update command to update at most one document in the collection.
func (dao *Mail) UpdateOneByID(ctx context.Context, id string, updateFunc MailUpdateFunc, optionsFunc ...MailUpdateOptionsFunc) (*mongo.UpdateResult, error) {
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, err
}
return dao.UpdateOne(ctx, func(cols *MailColumns) interface{} {
return bson.M{"_id": objectID}
}, updateFunc, optionsFunc...)
}
// UpdateMany executes an update command to update documents in the collection.
func (dao *Mail) UpdateMany(ctx context.Context, filterFunc MailFilterFunc, updateFunc MailUpdateFunc, optionsFunc ...MailUpdateOptionsFunc) (*mongo.UpdateResult, error) {
var (
opts *options.UpdateOptions
filter = filterFunc(dao.Columns)
update = updateFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.UpdateMany(ctx, filter, update, opts)
}
// FindOne executes a find command and returns a model for one document in the collection.
func (dao *Mail) FindOne(ctx context.Context, filterFunc MailFilterFunc, optionsFunc ...MailFindOneOptionsFunc) (*models.Mail, error) {
var (
opts *options.FindOneOptions
model = &models.Mail{}
filter = filterFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
err := dao.Collection.FindOne(ctx, filter, opts).Decode(model)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return model, nil
}
// FindOneByID executes a find command and returns a model for one document in the collection.
func (dao *Mail) FindOneByID(ctx context.Context, id string, optionsFunc ...MailFindOneOptionsFunc) (*models.Mail, error) {
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, err
}
return dao.FindOne(ctx, func(cols *MailColumns) interface{} {
return bson.M{"_id": objectID}
}, optionsFunc...)
}
// FindMany executes a find command and returns many models the matching documents in the collection.
func (dao *Mail) FindMany(ctx context.Context, filterFunc MailFilterFunc, optionsFunc ...MailFindManyOptionsFunc) ([]*models.Mail, error) {
var (
opts *options.FindOptions
filter = filterFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
cur, err := dao.Collection.Find(ctx, filter, opts)
if err != nil {
return nil, err
}
models := make([]*models.Mail, 0)
if err = cur.All(ctx, &models); err != nil {
return nil, err
}
return models, nil
}
// DeleteOne executes a delete command to delete at most one document from the collection.
func (dao *Mail) DeleteOne(ctx context.Context, filterFunc MailFilterFunc, optionsFunc ...MailDeleteOptionsFunc) (*mongo.DeleteResult, error) {
var (
opts *options.DeleteOptions
filter = filterFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.DeleteOne(ctx, filter, opts)
}
// DeleteOneByID executes a delete command to delete at most one document from the collection.
func (dao *Mail) DeleteOneByID(ctx context.Context, id string, optionsFunc ...MailDeleteOptionsFunc) (*mongo.DeleteResult, error) {
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, err
}
return dao.DeleteOne(ctx, func(cols *MailColumns) interface{} {
return bson.M{"_id": objectID}
}, optionsFunc...)
}
// DeleteMany executes a delete command to delete documents from the collection.
func (dao *Mail) DeleteMany(ctx context.Context, filterFunc MailFilterFunc, optionsFunc ...MailDeleteOptionsFunc) (*mongo.DeleteResult, error) {
var (
opts *options.DeleteOptions
filter = filterFunc(dao.Columns)
)
if len(optionsFunc) > 0 {
opts = optionsFunc[0](dao.Columns)
}
return dao.Collection.DeleteMany(ctx, filter, opts)
}
// autofill when inserting data
func (dao *Mail) autofill(ctx context.Context, model *models.Mail) error {
if model.ID.IsZero() {
model.ID = primitive.NewObjectID()
}
if model.SendTime == 0 {
model.SendTime = primitive.NewDateTimeFromTime(time.Now())
}
return nil
}
```
dao/mail.go
```go
package dao
import (
"github.com/dobyte/mongo-dao-generator/example/dao/internal"
"go.mongodb.org/mongo-driver/mongo"
)
type MailColumns = internal.MailColumns
type Mail struct {
*internal.Mail
}
func NewMail(db *mongo.Database) *Mail {
return &Mail{Mail: internal.NewMail(db)}
}
```
###### 6-4.使用生成的dao文件
```go
package main
import (
"context"
"github.com/dobyte/mongo-dao-generator/example/dao"
"github.com/dobyte/mongo-dao-generator/example/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
"log"
"time"
)
func main() {
var (
uri = "mongodb://root:12345678@127.0.0.1:27017"
opts = options.Client().ApplyURI(uri)
baseCtx = context.Background()
)
ctx, cancel := context.WithTimeout(baseCtx, 5*time.Second)
client, err := mongo.Connect(ctx, opts)
cancel()
if err != nil {
log.Fatalf("connect mongo server failed: %v", err)
}
ctx, cancel = context.WithTimeout(baseCtx, 5*time.Second)
defer cancel()
err = client.Ping(ctx, readpref.Primary())
cancel()
if err != nil {
log.Fatalf("ping mongo server failed: %v", err)
}
db := client.Database("dao_test")
mailDao := dao.NewMail(db)
_, err = mailDao.InsertOne(baseCtx, &model.Mail{
Title: "mongo-dao-generator introduction",
Content: "the mongo-dao-generator is a tool for automatically generating MongoDB Data Access Object.",
Sender: 1,
Receiver: 2,
Status: 1,
})
if err != nil {
log.Fatalf("failed to insert into mongo database: %v", err)
}
mail, err := mailDao.FindOne(baseCtx, func(cols *dao.MailColumns) interface{} {
return bson.M{cols.Receiver: 2}
})
if err != nil {
log.Fatalf("failed to find a row of data from mongo database: %v", err)
}
log.Printf("%+v", mail)
}
```
运行结果:
```bash
2023/02/17 16:05:31 &{ID:ObjectID("63ef354a4ddc485f0d9c5ea3") Title:mongo-dao-generator introduction Content:the mongo-dao-generator is a tool for automatically generating MongoDB Data Access Object. Sender:1 Receiver:2 Status:1 SendTime:1676621130323}
```