mongoctl工具
This commit is contained in:
parent
94ad9f9835
commit
81a0e50bca
|
@ -0,0 +1,3 @@
|
|||
.idea/
|
||||
*/.DS_Store
|
||||
.vscode
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 dobyte
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,483 @@
|
|||
# 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}
|
||||
```
|
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type counter struct {
|
||||
opts *options
|
||||
modelName string
|
||||
daoClassName string
|
||||
daoVariableName string
|
||||
daoPkgPath string
|
||||
daoPkgName string
|
||||
daoOutputDir string
|
||||
daoOutputFile string
|
||||
daoPrefixName string
|
||||
collectionName string
|
||||
}
|
||||
|
||||
func newCounter(opts *options) *counter {
|
||||
c := &counter{}
|
||||
c.opts = opts
|
||||
c.modelName = toPascalCase(opts.counterName)
|
||||
c.daoClassName = toPascalCase(c.modelName)
|
||||
c.daoVariableName = toCamelCase(c.modelName)
|
||||
c.daoOutputFile = fmt.Sprintf("%s.go", toFileName(c.modelName, c.opts.fileNameStyle))
|
||||
c.collectionName = toUnderscoreCase(c.modelName)
|
||||
|
||||
dir := strings.TrimSuffix(opts.daoDir, "/")
|
||||
|
||||
if opts.subPkgEnable {
|
||||
c.daoOutputDir = dir + "/" + toPackagePath(c.modelName, c.opts.subPkgStyle)
|
||||
} else {
|
||||
c.daoOutputDir = dir
|
||||
c.daoPrefixName = toPascalCase(c.modelName)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *counter) setDaoPkgPath(path string) {
|
||||
if c.opts.subPkgEnable {
|
||||
c.daoPkgPath = path + "/" + toPackagePath(c.modelName, c.opts.subPkgStyle)
|
||||
} else {
|
||||
c.daoPkgPath = path
|
||||
}
|
||||
|
||||
c.daoPkgName = toPackageName(filepath.Base(c.daoPkgPath))
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"mongo.games.com/mongoctl/example/dao/internal"
|
||||
)
|
||||
|
||||
type Counter struct {
|
||||
*internal.Counter
|
||||
}
|
||||
|
||||
func NewCounter(db *mongo.Database) *Counter {
|
||||
return &Counter{Counter: internal.NewCounter(db)}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// --------------------------------------------------------------------------------------------------
|
||||
// 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"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Counter struct {
|
||||
Columns *CounterColumns
|
||||
Database *mongo.Database
|
||||
Collection *mongo.Collection
|
||||
}
|
||||
|
||||
type CounterModel struct {
|
||||
ID string `bson:"_id"`
|
||||
Value int64 `bson:"value"`
|
||||
}
|
||||
|
||||
type CounterColumns struct {
|
||||
ID string
|
||||
Value string
|
||||
}
|
||||
|
||||
var counterColumns = &CounterColumns{
|
||||
ID: "_id",
|
||||
Value: "value",
|
||||
}
|
||||
|
||||
func NewCounter(db *mongo.Database) *Counter {
|
||||
return &Counter{
|
||||
Columns: counterColumns,
|
||||
Database: db,
|
||||
Collection: db.Collection("counter"),
|
||||
}
|
||||
}
|
||||
|
||||
// Incr 自增值
|
||||
func (dao *Counter) Incr(ctx context.Context, key string, incr ...int) (int64, error) {
|
||||
var (
|
||||
upsert = true
|
||||
returnDocument = options.After
|
||||
counter = &CounterModel{}
|
||||
value = 1
|
||||
)
|
||||
|
||||
if len(incr) > 0 {
|
||||
if incr[0] == 0 {
|
||||
return 0, errors.New("invalid increment value")
|
||||
}
|
||||
value = incr[0]
|
||||
}
|
||||
|
||||
rst := dao.Collection.FindOneAndUpdate(ctx, bson.M{
|
||||
dao.Columns.ID: key,
|
||||
}, bson.M{"$inc": bson.M{
|
||||
dao.Columns.Value: value,
|
||||
}}, &options.FindOneAndUpdateOptions{
|
||||
Upsert: &upsert,
|
||||
ReturnDocument: &returnDocument,
|
||||
})
|
||||
|
||||
if err := rst.Decode(counter); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return counter.Value, nil
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
// --------------------------------------------------------------------------------------------
|
||||
// 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"
|
||||
"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"
|
||||
modelpkg "mongo.games.com/mongoctl/example/model"
|
||||
"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 *modelpkg.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 []*modelpkg.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) (*modelpkg.Mail, error) {
|
||||
var (
|
||||
opts *options.FindOneOptions
|
||||
model = &modelpkg.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) (*modelpkg.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) ([]*modelpkg.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([]*modelpkg.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 *modelpkg.Mail) error {
|
||||
if model.ID.IsZero() {
|
||||
model.ID = primitive.NewObjectID()
|
||||
}
|
||||
|
||||
if model.SendTime == 0 {
|
||||
model.SendTime = primitive.NewDateTimeFromTime(time.Now())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
// --------------------------------------------------------------------------------------------
|
||||
// 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"
|
||||
"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"
|
||||
modelpkg "mongo.games.com/mongoctl/example/model"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserFilterFunc func(cols *UserColumns) interface{}
|
||||
type UserUpdateFunc func(cols *UserColumns) interface{}
|
||||
type UserPipelineFunc func(cols *UserColumns) interface{}
|
||||
type UserCountOptionsFunc func(cols *UserColumns) *options.CountOptions
|
||||
type UserAggregateOptionsFunc func(cols *UserColumns) *options.AggregateOptions
|
||||
type UserFindOneOptionsFunc func(cols *UserColumns) *options.FindOneOptions
|
||||
type UserFindManyOptionsFunc func(cols *UserColumns) *options.FindOptions
|
||||
type UserUpdateOptionsFunc func(cols *UserColumns) *options.UpdateOptions
|
||||
type UserDeleteOptionsFunc func(cols *UserColumns) *options.DeleteOptions
|
||||
type UserInsertOneOptionsFunc func(cols *UserColumns) *options.InsertOneOptions
|
||||
type UserInsertManyOptionsFunc func(cols *UserColumns) *options.InsertManyOptions
|
||||
|
||||
type User struct {
|
||||
Columns *UserColumns
|
||||
Database *mongo.Database
|
||||
Collection *mongo.Collection
|
||||
}
|
||||
|
||||
type UserColumns struct {
|
||||
ID string
|
||||
UID string // 用户ID
|
||||
Account string // 用户账号
|
||||
Password string // 用户密码
|
||||
Salt string // 密码
|
||||
Mobile string // 用户手机
|
||||
Email string // 用户邮箱
|
||||
Nickname string // 用户昵称
|
||||
Signature string // 用户签名
|
||||
Gender string // 用户性别
|
||||
Level string // 用户等级
|
||||
Experience string // 用户经验
|
||||
Coin string // 用户金币
|
||||
Type string // 用户类型
|
||||
Status string // 用户状态
|
||||
DeviceID string // 设备ID
|
||||
ThirdPlatforms string // 第三方平台
|
||||
RegisterIP string // 注册IP
|
||||
RegisterTime string // 注册时间
|
||||
LastLoginIP string // 最近登录IP
|
||||
LastLoginTime string // 最近登录时间
|
||||
}
|
||||
|
||||
var userColumns = &UserColumns{
|
||||
ID: "_id",
|
||||
UID: "uid", // 用户ID
|
||||
Account: "account", // 用户账号
|
||||
Password: "password", // 用户密码
|
||||
Salt: "salt", // 密码
|
||||
Mobile: "mobile", // 用户手机
|
||||
Email: "email", // 用户邮箱
|
||||
Nickname: "nickname", // 用户昵称
|
||||
Signature: "signature", // 用户签名
|
||||
Gender: "gender", // 用户性别
|
||||
Level: "level", // 用户等级
|
||||
Experience: "experience", // 用户经验
|
||||
Coin: "coin", // 用户金币
|
||||
Type: "type", // 用户类型
|
||||
Status: "status", // 用户状态
|
||||
DeviceID: "device_id", // 设备ID
|
||||
ThirdPlatforms: "third_platforms", // 第三方平台
|
||||
RegisterIP: "register_ip", // 注册IP
|
||||
RegisterTime: "register_time", // 注册时间
|
||||
LastLoginIP: "last_login_ip", // 最近登录IP
|
||||
LastLoginTime: "last_login_time", // 最近登录时间
|
||||
}
|
||||
|
||||
func NewUser(db *mongo.Database) *User {
|
||||
return &User{
|
||||
Columns: userColumns,
|
||||
Database: db,
|
||||
Collection: db.Collection("user"),
|
||||
}
|
||||
}
|
||||
|
||||
// Count returns the number of documents in the collection.
|
||||
func (dao *User) Count(ctx context.Context, filterFunc UserFilterFunc, optionsFunc ...UserCountOptionsFunc) (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 *User) Aggregate(ctx context.Context, pipelineFunc UserPipelineFunc, optionsFunc ...UserAggregateOptionsFunc) (*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 *User) InsertOne(ctx context.Context, model *modelpkg.User, optionsFunc ...UserInsertOneOptionsFunc) (*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 *User) InsertMany(ctx context.Context, models []*modelpkg.User, optionsFunc ...UserInsertManyOptionsFunc) (*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 *User) UpdateOne(ctx context.Context, filterFunc UserFilterFunc, updateFunc UserUpdateFunc, optionsFunc ...UserUpdateOptionsFunc) (*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 *User) UpdateOneByID(ctx context.Context, id string, updateFunc UserUpdateFunc, optionsFunc ...UserUpdateOptionsFunc) (*mongo.UpdateResult, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.UpdateOne(ctx, func(cols *UserColumns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, updateFunc, optionsFunc...)
|
||||
}
|
||||
|
||||
// UpdateMany executes an update command to update documents in the collection.
|
||||
func (dao *User) UpdateMany(ctx context.Context, filterFunc UserFilterFunc, updateFunc UserUpdateFunc, optionsFunc ...UserUpdateOptionsFunc) (*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 *User) FindOne(ctx context.Context, filterFunc UserFilterFunc, optionsFunc ...UserFindOneOptionsFunc) (*modelpkg.User, error) {
|
||||
var (
|
||||
opts *options.FindOneOptions
|
||||
model = &modelpkg.User{}
|
||||
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 *User) FindOneByID(ctx context.Context, id string, optionsFunc ...UserFindOneOptionsFunc) (*modelpkg.User, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.FindOne(ctx, func(cols *UserColumns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, optionsFunc...)
|
||||
}
|
||||
|
||||
// FindMany executes a find command and returns many models the matching documents in the collection.
|
||||
func (dao *User) FindMany(ctx context.Context, filterFunc UserFilterFunc, optionsFunc ...UserFindManyOptionsFunc) ([]*modelpkg.User, 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([]*modelpkg.User, 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 *User) DeleteOne(ctx context.Context, filterFunc UserFilterFunc, optionsFunc ...UserDeleteOptionsFunc) (*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 *User) DeleteOneByID(ctx context.Context, id string, optionsFunc ...UserDeleteOptionsFunc) (*mongo.DeleteResult, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.DeleteOne(ctx, func(cols *UserColumns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, optionsFunc...)
|
||||
}
|
||||
|
||||
// DeleteMany executes a delete command to delete documents from the collection.
|
||||
func (dao *User) DeleteMany(ctx context.Context, filterFunc UserFilterFunc, optionsFunc ...UserDeleteOptionsFunc) (*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 *User) autofill(ctx context.Context, model *modelpkg.User) error {
|
||||
if model.ID.IsZero() {
|
||||
model.ID = primitive.NewObjectID()
|
||||
}
|
||||
|
||||
if model.UID == 0 {
|
||||
if id, err := NewCounter(dao.Database).Incr(ctx, "uid"); err != nil {
|
||||
return err
|
||||
} else {
|
||||
model.UID = int32(id)
|
||||
}
|
||||
}
|
||||
|
||||
if model.RegisterTime == 0 {
|
||||
model.RegisterTime = primitive.NewDateTimeFromTime(time.Now())
|
||||
}
|
||||
|
||||
if model.LastLoginTime == 0 {
|
||||
model.LastLoginTime = primitive.NewDateTimeFromTime(time.Now())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"mongo.games.com/mongoctl/example/dao/internal"
|
||||
)
|
||||
|
||||
type MailColumns = internal.MailColumns
|
||||
|
||||
type Mail struct {
|
||||
*internal.Mail
|
||||
}
|
||||
|
||||
func NewMail(db *mongo.Database, c *mongo.Collection) *Mail {
|
||||
v := internal.NewMail(nil)
|
||||
v.Database = db
|
||||
v.Collection = c
|
||||
panic("创建索引")
|
||||
//c.Indexes().CreateOne()
|
||||
//c.Indexes().CreateMany()
|
||||
return &Mail{Mail: v}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package dao
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"mongo.games.com/mongoctl/example/dao/internal"
|
||||
)
|
||||
|
||||
type UserColumns = internal.UserColumns
|
||||
|
||||
type User struct {
|
||||
*internal.User
|
||||
}
|
||||
|
||||
func NewUser(db *mongo.Database, c *mongo.Collection) *User {
|
||||
v := internal.NewUser(nil)
|
||||
v.Database = db
|
||||
v.Collection = c
|
||||
panic("创建索引")
|
||||
//c.Indexes().CreateOne()
|
||||
//c.Indexes().CreateMany()
|
||||
return &User{User: v}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
|
||||
"mongo.games.com/mongoctl/example/dao"
|
||||
"mongo.games.com/mongoctl/example/model"
|
||||
)
|
||||
|
||||
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, db.Collection("mail"))
|
||||
|
||||
_, 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)
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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"` // 发送时间
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package model
|
||||
|
||||
import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
type Gender int
|
||||
|
||||
const (
|
||||
GenderUnknown Gender = iota // 未知
|
||||
GenderMale // 男性
|
||||
GenderFemale // 女性
|
||||
)
|
||||
|
||||
// Type 用户类型
|
||||
type Type int
|
||||
|
||||
const (
|
||||
TypeRobot Type = 0 // 机器人用户
|
||||
TypeGuest Type = 1 // 游客用户
|
||||
TypeGeneral Type = 2 // 普通用户
|
||||
TypeSystem Type = 3 // 系统用户
|
||||
)
|
||||
|
||||
// Status 用户状态
|
||||
type Status int
|
||||
|
||||
const (
|
||||
StatusNormal Status = iota // 正常
|
||||
StatusForbidden // 封禁
|
||||
)
|
||||
|
||||
//go:generate mongoctl -model-dir=. -model-names=User -dao-dir=../dao/
|
||||
type User struct {
|
||||
ID primitive.ObjectID `bson:"_id" gen:"autoFill"`
|
||||
UID int32 `bson:"uid" gen:"autoIncr:uid"` // 用户ID
|
||||
Account string `bson:"account"` // 用户账号
|
||||
Password string `bson:"password"` // 用户密码
|
||||
Salt string `bson:"salt"` // 密码
|
||||
Mobile string `bson:"mobile"` // 用户手机
|
||||
Email string `bson:"email"` // 用户邮箱
|
||||
Nickname string `bson:"nickname"` // 用户昵称
|
||||
Signature string `bson:"signature"` // 用户签名
|
||||
Gender Gender `bson:"gender"` // 用户性别
|
||||
Level int `bson:"level"` // 用户等级
|
||||
Experience int `bson:"experience"` // 用户经验
|
||||
Coin int `bson:"coin"` // 用户金币
|
||||
Type Type `bson:"type"` // 用户类型
|
||||
Status Status `bson:"status"` // 用户状态
|
||||
DeviceID string `bson:"device_id"` // 设备ID
|
||||
ThirdPlatforms ThirdPlatforms `bson:"third_platforms"` // 第三方平台
|
||||
RegisterIP string `bson:"register_ip"` // 注册IP
|
||||
RegisterTime primitive.DateTime `bson:"register_time" gen:"autoFill"` // 注册时间
|
||||
LastLoginIP string `bson:"last_login_ip"` // 最近登录IP
|
||||
LastLoginTime primitive.DateTime `bson:"last_login_time" gen:"autoFill"` // 最近登录时间
|
||||
}
|
||||
|
||||
// ThirdPlatforms 第三方平台
|
||||
type ThirdPlatforms struct {
|
||||
Wechat string `bson:"wechat"` // 微信登录openid
|
||||
Google string `bson:"google"` // 谷歌登录userid
|
||||
Facebook string `bson:"facebook"` // 脸书登录userid
|
||||
}
|
|
@ -0,0 +1,393 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"log"
|
||||
"mongo.games.com/mongoctl/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
symbolBacktick = "`"
|
||||
)
|
||||
|
||||
const (
|
||||
symbolBacktickKey = "SymbolBacktick"
|
||||
)
|
||||
|
||||
const (
|
||||
varPackagesKey = "VarPackages"
|
||||
varModelClassNameKey = "VarModelClassName"
|
||||
varModelPackageNameKey = "VarModelPackageName"
|
||||
varModelPackagePathKey = "VarModelPackagePath"
|
||||
varModelVariableNameKey = "VarModelVariableName"
|
||||
varModelColumnsDefineKey = "VarModelColumnsDefine"
|
||||
varModelColumnsInstanceKey = "VarModelColumnsInstance"
|
||||
varDaoClassNameKey = "VarDaoClassName"
|
||||
varDaoVariableNameKey = "VarDaoVariableName"
|
||||
varDaoPackageNameKey = "VarDaoPackageName"
|
||||
varDaoPackagePathKey = "VarDaoPackagePath"
|
||||
varDaoPrefixNameKey = "VarDaoPrefixName"
|
||||
varCollectionNameKey = "VarCollectionName"
|
||||
varAutofillCodeKey = "VarAutofillCode"
|
||||
)
|
||||
|
||||
const defaultCounterName = "Counter"
|
||||
|
||||
type options struct {
|
||||
modelDir string //
|
||||
modelPkgPath string //
|
||||
modelPkgAlias string //
|
||||
modelNames []string //
|
||||
daoDir string
|
||||
daoPkgPath string
|
||||
subPkgEnable bool
|
||||
subPkgStyle style
|
||||
counterName string
|
||||
fileNameStyle style
|
||||
}
|
||||
|
||||
type generator struct {
|
||||
opts *options
|
||||
counter *counter
|
||||
modelNames map[string]struct{}
|
||||
}
|
||||
|
||||
func newGenerator(opts *options) *generator {
|
||||
modelNames := make(map[string]struct{}, len(opts.modelNames))
|
||||
for _, modelName := range opts.modelNames {
|
||||
if isExportable(modelName) { // 是否导出字段
|
||||
modelNames[modelName] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if len(modelNames) == 0 {
|
||||
log.Fatalf("error: %d model type names found", len(modelNames))
|
||||
}
|
||||
|
||||
if opts.counterName == "" {
|
||||
opts.counterName = defaultCounterName
|
||||
}
|
||||
|
||||
return &generator{
|
||||
opts: opts,
|
||||
counter: newCounter(opts),
|
||||
modelNames: modelNames,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) makeDao() {
|
||||
models := g.parseModels()
|
||||
|
||||
for _, m := range models {
|
||||
g.makeModelInternalDao(m)
|
||||
|
||||
g.makeModelExternalDao(m)
|
||||
|
||||
fmt.Printf("%s's dao file generated successfully\n", m.modelName)
|
||||
|
||||
if !m.isDependCounter {
|
||||
continue
|
||||
}
|
||||
|
||||
g.makeCounterInternalDao()
|
||||
|
||||
g.makeCounterExternalDao()
|
||||
}
|
||||
}
|
||||
|
||||
// generate an internal dao file based on model
|
||||
func (g *generator) makeModelInternalDao(m *model) {
|
||||
replaces := make(map[string]string)
|
||||
replaces[varModelClassNameKey] = m.modelClassName
|
||||
replaces[varModelPackageNameKey] = m.modelPkgName
|
||||
replaces[varModelPackagePathKey] = m.modelPkgPath
|
||||
replaces[varModelVariableNameKey] = m.modelVariableName
|
||||
replaces[varDaoPrefixNameKey] = m.daoPrefixName
|
||||
replaces[varDaoClassNameKey] = m.daoClassName
|
||||
replaces[varDaoVariableNameKey] = m.daoVariableName
|
||||
replaces[varCollectionNameKey] = m.collectionName
|
||||
replaces[varModelColumnsDefineKey] = m.modelColumnsDefined()
|
||||
replaces[varModelColumnsInstanceKey] = m.modelColumnsInstance()
|
||||
replaces[varAutofillCodeKey] = m.autoFillCode()
|
||||
replaces[varPackagesKey] = m.packages()
|
||||
|
||||
file := m.daoOutputDir + "/internal/" + m.daoOutputFile
|
||||
|
||||
err := doWrite(file, template.InternalTemplate, replaces)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// generate an external dao file based on model
|
||||
func (g *generator) makeModelExternalDao(m *model) {
|
||||
file := m.daoOutputDir + "/" + m.daoOutputFile
|
||||
|
||||
_, err := os.Stat(file)
|
||||
if err != nil {
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
// ignore
|
||||
case os.IsExist(err):
|
||||
return
|
||||
default:
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
replaces := make(map[string]string)
|
||||
replaces[varDaoClassNameKey] = m.daoClassName
|
||||
replaces[varDaoPrefixNameKey] = m.daoPrefixName
|
||||
replaces[varDaoPackageNameKey] = m.daoPkgName
|
||||
replaces[varDaoPackagePathKey] = m.daoPkgPath
|
||||
|
||||
err = doWrite(file, template.ExternalTemplate, replaces)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// generate an internal dao file based on counter model
|
||||
func (g *generator) makeCounterInternalDao() {
|
||||
replaces := make(map[string]string)
|
||||
replaces[varDaoClassNameKey] = g.counter.daoClassName
|
||||
replaces[varDaoPrefixNameKey] = g.counter.daoPrefixName
|
||||
replaces[varDaoVariableNameKey] = g.counter.daoVariableName
|
||||
replaces[varCollectionNameKey] = g.counter.collectionName
|
||||
replaces[symbolBacktickKey] = symbolBacktick
|
||||
|
||||
file := g.counter.daoOutputDir + "/internal/" + g.counter.daoOutputFile
|
||||
|
||||
err := doWrite(file, template.CounterInternalTemplate, replaces)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// generate an external dao file based on counter model
|
||||
func (g *generator) makeCounterExternalDao() {
|
||||
file := g.counter.daoOutputDir + "/" + g.counter.daoOutputFile
|
||||
|
||||
_, err := os.Stat(file)
|
||||
if err != nil {
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
// ignore
|
||||
case os.IsExist(err):
|
||||
return
|
||||
default:
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
replaces := make(map[string]string)
|
||||
replaces[varDaoClassNameKey] = g.counter.daoClassName
|
||||
replaces[varDaoPackageNameKey] = g.counter.daoPkgName
|
||||
replaces[varDaoPackagePathKey] = g.counter.daoPkgPath
|
||||
|
||||
err = doWrite(file, template.CounterExternalTemplate, replaces)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// parse multiple models from the go file
|
||||
func (g *generator) parseModels() []*model {
|
||||
var (
|
||||
pkg = g.loadPackage()
|
||||
models = make([]*model, 0, len(pkg.Syntax))
|
||||
daoPkgPath = g.opts.daoPkgPath
|
||||
modelPkgPath = g.opts.modelPkgPath
|
||||
modelPkgName = g.opts.modelPkgAlias
|
||||
)
|
||||
|
||||
if g.opts.daoPkgPath == "" && pkg.Module != nil {
|
||||
outPath, err := filepath.Abs(g.opts.daoDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
daoPkgPath = pkg.Module.Path + outPath[len(pkg.Module.Dir):]
|
||||
}
|
||||
|
||||
daoPkgPath = strings.ReplaceAll(daoPkgPath, `\`, `/`)
|
||||
|
||||
g.counter.setDaoPkgPath(daoPkgPath)
|
||||
|
||||
for _, file := range pkg.Syntax {
|
||||
if g.opts.modelPkgPath == "" && pkg.Module != nil && pkg.Fset != nil {
|
||||
filePath := filepath.Dir(pkg.Fset.Position(file.Package).Filename)
|
||||
modelPkgPath = pkg.Module.Path + filePath[len(pkg.Module.Dir):]
|
||||
}
|
||||
|
||||
modelPkgPath = strings.ReplaceAll(modelPkgPath, `\`, `/`)
|
||||
modelPkgName = file.Name.Name
|
||||
|
||||
ast.Inspect(file, func(node ast.Node) bool {
|
||||
decl, ok := node.(*ast.GenDecl)
|
||||
if !ok || decl.Tok != token.TYPE {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, s := range decl.Specs {
|
||||
spec, ok := s.(*ast.TypeSpec)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
_, ok = g.modelNames[spec.Name.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
st, ok := spec.Type.(*ast.StructType)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
model := newModel(g.opts)
|
||||
model.setModelName(spec.Name.Name)
|
||||
model.setModelPkg(modelPkgName, modelPkgPath)
|
||||
model.setDaoPkgPath(daoPkgPath)
|
||||
|
||||
for _, item := range st.Fields.List {
|
||||
name := item.Names[0].Name
|
||||
|
||||
if !isExportable(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
field := &field{name: name, column: name}
|
||||
|
||||
if item.Tag != nil && len(item.Tag.Value) > 2 {
|
||||
runes := []rune(item.Tag.Value)
|
||||
if runes[0] != '`' || runes[len(runes)-1] != '`' {
|
||||
continue
|
||||
}
|
||||
|
||||
tag := reflect.StructTag(runes[1 : len(runes)-1])
|
||||
|
||||
if column := tag.Get("bson"); column != "" {
|
||||
field.column = column
|
||||
}
|
||||
|
||||
val, ok := tag.Lookup("gen")
|
||||
if ok {
|
||||
parts := strings.Split(val, ";")
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch eles := strings.SplitN(part, ":", 2); eles[0] {
|
||||
case "autoFill":
|
||||
expr, ok := item.Type.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
switch fmt.Sprintf("%s.%s", expr.X.(*ast.Ident).Name, expr.Sel.Name) {
|
||||
case "primitive.ObjectID":
|
||||
field.autoFill = objectID
|
||||
model.addImport(pkg3)
|
||||
case "primitive.DateTime":
|
||||
field.autoFill = dateTime
|
||||
model.addImport(pkg1)
|
||||
model.addImport(pkg3)
|
||||
}
|
||||
case "autoIncr":
|
||||
if len(eles) != 2 || eles[1] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
expr, ok := item.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
switch expr.Name {
|
||||
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
|
||||
field.autoFill = autoIncr
|
||||
field.autoIncrFieldName = eles[1]
|
||||
|
||||
if g.opts.subPkgEnable {
|
||||
model.addImport(g.counter.daoPkgPath)
|
||||
}
|
||||
|
||||
switch expr.Name {
|
||||
case "int":
|
||||
field.autoIncrFieldKind = reflect.Int
|
||||
case "int8":
|
||||
field.autoIncrFieldKind = reflect.Int8
|
||||
case "int16":
|
||||
field.autoIncrFieldKind = reflect.Int16
|
||||
case "int32":
|
||||
field.autoIncrFieldKind = reflect.Int32
|
||||
case "int64":
|
||||
field.autoIncrFieldKind = reflect.Int64
|
||||
case "uint":
|
||||
field.autoIncrFieldKind = reflect.Uint
|
||||
case "uint8":
|
||||
field.autoIncrFieldKind = reflect.Uint8
|
||||
case "uint16":
|
||||
field.autoIncrFieldKind = reflect.Uint16
|
||||
case "uint32":
|
||||
field.autoIncrFieldKind = reflect.Uint32
|
||||
case "uint64":
|
||||
field.autoIncrFieldKind = reflect.Uint64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if item.Doc != nil {
|
||||
field.documents = make([]string, 0, len(item.Doc.List))
|
||||
for _, doc := range item.Doc.List {
|
||||
field.documents = append(field.documents, doc.Text)
|
||||
}
|
||||
}
|
||||
|
||||
if item.Comment != nil {
|
||||
field.comment = item.Comment.List[0].Text
|
||||
}
|
||||
|
||||
model.addFields(field)
|
||||
}
|
||||
|
||||
models = append(models, model)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return models
|
||||
}
|
||||
|
||||
func (g *generator) loadPackage() *packages.Package {
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedModule,
|
||||
Tests: false,
|
||||
}
|
||||
pkgs, err := packages.Load(cfg, g.opts.modelDir)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if len(pkgs) != 1 {
|
||||
log.Fatalf("error: %d packages found", len(pkgs))
|
||||
}
|
||||
|
||||
return pkgs[0]
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
module mongo.games.com/mongoctl
|
||||
|
||||
go 1.22.5
|
||||
|
||||
require (
|
||||
go.mongodb.org/mongo-driver v1.17.1
|
||||
golang.org/x/tools v0.26.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
)
|
|
@ -0,0 +1,54 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestModule(t *testing.T) {
|
||||
m := newModel(&options{
|
||||
modelDir: "./model",
|
||||
modelPkgPath: "./modelpkgpath",
|
||||
modelPkgAlias: "test",
|
||||
modelNames: []string{"names"},
|
||||
daoDir: "./dao",
|
||||
daoPkgPath: "./daopkgpath",
|
||||
subPkgEnable: false,
|
||||
subPkgStyle: lowerCase,
|
||||
counterName: "",
|
||||
fileNameStyle: lowerCase,
|
||||
})
|
||||
|
||||
m.setModelName("mymodel")
|
||||
m.setModelPkg("mypkg", "mypath")
|
||||
m.setDaoPkgPath("daopath")
|
||||
|
||||
fmt.Println(m.packages())
|
||||
fmt.Println(m.modelColumnsInstance())
|
||||
fmt.Println(m.modelColumnsDefined())
|
||||
fmt.Println(m.autoFillCode())
|
||||
}
|
||||
|
||||
func TestToName(t *testing.T) {
|
||||
|
||||
var f func()
|
||||
f()
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
modelDir = flag.String("model-dir", "", "模型所在目录; 必需")
|
||||
modelNames = flag.String("model-names", "", "模型结构体名称; 必需")
|
||||
modelPkgPath = flag.String("model-pkg-path", "", "模型包名; 默认自动生成")
|
||||
modelPkgAlias = flag.String("model-pkg-alias", "", "模型包别名")
|
||||
daoDir = flag.String("dao-dir", "", "生成代码所在目录; 必需")
|
||||
daoPkgPath = flag.String("dao-pkg-path", "", "生成代码所在目录的包名; 默认自动生成")
|
||||
subPkgEnable = flag.Bool("sub-pkg-enable", false, "每个模型创建一个子包; 默认关闭")
|
||||
subPkgStyle = flag.String("sub-pkg-style", "kebab", "模型子包目录名称风格; 选项: kebab | underscore | lower | camel | pascal; 默认是 kebab")
|
||||
counterName = flag.String("counter-name", "", "自增模型名称; 默认是 counter")
|
||||
fileNameStyle = flag.String("file-style", "underscore", "代码文件名称风格; 选项: kebab | underscore | lower | camel | pascal; 默认是 underscore")
|
||||
)
|
||||
|
||||
// Usage is a replacement usage function for the flags package.
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "用法 mongoctl:\n")
|
||||
fmt.Fprintf(os.Stderr, "\tmongoctl [flags] -model-dir=. -model-names=T,T -dao-dir=./dao\n")
|
||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
//go:generate mongoctl -type=Mail,User
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("mongoctl: ")
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
if len(*modelDir) == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if len(*modelNames) == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if len(*daoDir) == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
newGenerator(&options{
|
||||
daoDir: *daoDir,
|
||||
daoPkgPath: *daoPkgPath,
|
||||
modelDir: *modelDir,
|
||||
modelNames: strings.Split(*modelNames, ","),
|
||||
modelPkgPath: *modelPkgPath,
|
||||
modelPkgAlias: *modelPkgAlias,
|
||||
subPkgEnable: *subPkgEnable,
|
||||
subPkgStyle: style(*subPkgStyle),
|
||||
counterName: *counterName,
|
||||
fileNameStyle: style(*fileNameStyle),
|
||||
}).makeDao()
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultModelPkgAlias = "modelpkg"
|
||||
defaultModelVariableName = "model"
|
||||
)
|
||||
|
||||
type autoFill int
|
||||
|
||||
const (
|
||||
objectID autoFill = iota + 1 // primitive.NewObjectID()
|
||||
dateTime // primitive.NewDateTimeFromTime(time.Now())
|
||||
autoIncr // auto-increment
|
||||
)
|
||||
|
||||
const (
|
||||
pkg1 = "time"
|
||||
pkg2 = "context"
|
||||
pkg3 = "go.mongodb.org/mongo-driver/bson/primitive"
|
||||
pkg4 = "go.mongodb.org/mongo-driver/mongo"
|
||||
pkg5 = "go.mongodb.org/mongo-driver/mongo/options"
|
||||
pkg6 = "errors"
|
||||
pkg7 = "go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type field struct {
|
||||
name string
|
||||
column string
|
||||
comment string
|
||||
documents []string
|
||||
autoFill autoFill
|
||||
autoIncrFieldName string
|
||||
autoIncrFieldKind reflect.Kind
|
||||
}
|
||||
|
||||
type model struct {
|
||||
opts *options
|
||||
fields []*field
|
||||
imports map[string]string
|
||||
modelName string
|
||||
modelClassName string
|
||||
modelVariableName string
|
||||
modelPkgPath string
|
||||
modelPkgName string
|
||||
daoClassName string
|
||||
daoVariableName string
|
||||
daoPkgPath string
|
||||
daoPkgName string
|
||||
daoOutputDir string
|
||||
daoOutputFile string
|
||||
daoPrefixName string
|
||||
collectionName string
|
||||
fieldNameMaxLen int
|
||||
fieldComplexMaxLen int
|
||||
isDependCounter bool
|
||||
}
|
||||
|
||||
func newModel(opts *options) *model {
|
||||
m := &model{
|
||||
opts: opts,
|
||||
fields: make([]*field, 0),
|
||||
imports: make(map[string]string, 8),
|
||||
}
|
||||
|
||||
m.addImport(pkg2)
|
||||
m.addImport(pkg4)
|
||||
m.addImport(pkg5)
|
||||
m.addImport(pkg6)
|
||||
m.addImport(pkg7)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *model) setModelName(name string) {
|
||||
m.modelName = name
|
||||
m.modelClassName = toPascalCase(m.modelName)
|
||||
m.modelVariableName = toCamelCase(m.modelName)
|
||||
m.daoClassName = toPascalCase(m.modelName)
|
||||
m.daoVariableName = toCamelCase(m.modelName)
|
||||
m.daoOutputFile = fmt.Sprintf("%s.go", toFileName(m.modelName, m.opts.fileNameStyle))
|
||||
m.collectionName = toUnderscoreCase(m.modelName)
|
||||
|
||||
dir := strings.TrimSuffix(m.opts.daoDir, "/")
|
||||
|
||||
if m.opts.subPkgEnable {
|
||||
m.daoOutputDir = dir + "/" + toPackagePath(m.modelName, m.opts.subPkgStyle)
|
||||
} else {
|
||||
m.daoOutputDir = dir
|
||||
m.daoPrefixName = toPascalCase(m.modelName)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) setModelPkg(name, path string) {
|
||||
m.modelPkgPath = path
|
||||
|
||||
if m.opts.modelPkgAlias != "" {
|
||||
m.modelPkgName = m.opts.modelPkgAlias
|
||||
m.addImport(m.modelPkgPath, m.modelPkgName)
|
||||
} else {
|
||||
m.modelPkgName = name
|
||||
m.addImport(m.modelPkgPath)
|
||||
}
|
||||
|
||||
if m.modelPkgName == defaultModelVariableName {
|
||||
m.modelPkgName = defaultModelPkgAlias
|
||||
m.addImport(m.modelPkgPath, m.modelPkgName)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) setDaoPkgPath(path string) {
|
||||
if m.opts.subPkgEnable {
|
||||
m.daoPkgPath = path + "/" + toPackagePath(m.modelName, m.opts.subPkgStyle)
|
||||
} else {
|
||||
m.daoPkgPath = path
|
||||
}
|
||||
|
||||
m.daoPkgName = toPackageName(filepath.Base(m.daoPkgPath))
|
||||
}
|
||||
|
||||
func (m *model) addImport(pkg string, alias ...string) {
|
||||
if len(alias) > 0 {
|
||||
m.imports[pkg] = alias[0]
|
||||
} else {
|
||||
m.imports[pkg] = ""
|
||||
}
|
||||
}
|
||||
|
||||
func (m *model) addFields(fields ...*field) {
|
||||
for _, f := range fields {
|
||||
if l := len(f.name); l > m.fieldNameMaxLen {
|
||||
m.fieldNameMaxLen = l
|
||||
}
|
||||
|
||||
if l := len(f.name) + len(f.column) + 5; l > m.fieldComplexMaxLen {
|
||||
m.fieldComplexMaxLen = l
|
||||
}
|
||||
|
||||
if f.autoFill == autoIncr {
|
||||
m.isDependCounter = true
|
||||
}
|
||||
}
|
||||
|
||||
m.fields = append(m.fields, fields...)
|
||||
}
|
||||
|
||||
func (m *model) modelColumnsDefined() (str string) {
|
||||
for i, f := range m.fields {
|
||||
str += fmt.Sprintf("\t%s%s%s %s", f.name, strings.Repeat(" ", m.fieldNameMaxLen-len(f.name)+1), "string", f.comment)
|
||||
if i != len(m.fields)-1 {
|
||||
str += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
str = strings.TrimPrefix(str, "\t")
|
||||
return
|
||||
}
|
||||
|
||||
func (m *model) modelColumnsInstance() (str string) {
|
||||
for i, f := range m.fields {
|
||||
s := fmt.Sprintf("%s:%s\"%s\",", f.name, strings.Repeat(" ", m.fieldNameMaxLen-len(f.name)+1), f.column)
|
||||
s += strings.Repeat(" ", m.fieldComplexMaxLen-len(s)+1) + f.comment
|
||||
str += "\t" + s
|
||||
if i != len(m.fields)-1 {
|
||||
str += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
str = strings.TrimLeft(str, "\t")
|
||||
return
|
||||
}
|
||||
|
||||
func (m *model) packages() (str string) {
|
||||
packages := make([]string, 0, len(m.imports))
|
||||
for pkg := range m.imports {
|
||||
packages = append(packages, pkg)
|
||||
}
|
||||
|
||||
sort.Slice(packages, func(i, j int) bool {
|
||||
return packages[i] < packages[j]
|
||||
})
|
||||
|
||||
for _, pkg := range packages {
|
||||
if alias := m.imports[pkg]; alias != "" {
|
||||
str += fmt.Sprintf("\t%s \"%s\"\n", alias, pkg)
|
||||
} else {
|
||||
str += fmt.Sprintf("\t\"%s\"\n", pkg)
|
||||
}
|
||||
}
|
||||
|
||||
str = strings.TrimPrefix(str, "\t")
|
||||
str = strings.TrimSuffix(str, "\n")
|
||||
return
|
||||
}
|
||||
|
||||
func (m *model) autoFillCode() (str string) {
|
||||
var (
|
||||
counterName = toPascalCase(m.opts.counterName)
|
||||
counterPkgPrefix string
|
||||
)
|
||||
|
||||
if m.opts.subPkgEnable {
|
||||
counterPkgPrefix = fmt.Sprintf("%s.", toPackageName(counterName))
|
||||
}
|
||||
|
||||
for _, f := range m.fields {
|
||||
if f.autoFill == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if str != "" {
|
||||
str += "\n\n"
|
||||
}
|
||||
|
||||
switch f.autoFill {
|
||||
case objectID:
|
||||
str += fmt.Sprintf("\tif model.%s.IsZero() {\n", f.name)
|
||||
str += fmt.Sprintf("\t\tmodel.%s = primitive.NewObjectID()\n", f.name)
|
||||
str += "\t}"
|
||||
case dateTime:
|
||||
str += fmt.Sprintf("\tif model.%s == 0 {\n", f.name)
|
||||
str += fmt.Sprintf("\t\tmodel.%s = primitive.NewDateTimeFromTime(time.Now())\n", f.name)
|
||||
str += "\t}"
|
||||
case autoIncr:
|
||||
str += fmt.Sprintf("\tif model.%s == 0 {\n", f.name)
|
||||
str += fmt.Sprintf("\t\tif id, err := %sNew%s(dao.Database).Incr(ctx, \"%s\"); err != nil {\n", counterPkgPrefix, counterName, f.autoIncrFieldName)
|
||||
str += "\t\t\treturn err\n"
|
||||
str += "\t\t} else {\n"
|
||||
|
||||
switch f.autoIncrFieldKind {
|
||||
case reflect.Int:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = int(id)\n", f.name)
|
||||
case reflect.Int8:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = int8(id)\n", f.name)
|
||||
case reflect.Int16:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = int16(id)\n", f.name)
|
||||
case reflect.Int32:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = int32(id)\n", f.name)
|
||||
case reflect.Int64:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = id\n", f.name)
|
||||
case reflect.Uint:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = uint(id)\n", f.name)
|
||||
case reflect.Uint8:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = uint8(id)\n", f.name)
|
||||
case reflect.Uint16:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = uint16(id)\n", f.name)
|
||||
case reflect.Uint32:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = uint32(id)\n", f.name)
|
||||
case reflect.Uint64:
|
||||
str += fmt.Sprintf("\t\t\tmodel.%s = uint64(id)\n", f.name)
|
||||
}
|
||||
|
||||
str += "\t\t}\n"
|
||||
str += "\t}"
|
||||
}
|
||||
}
|
||||
|
||||
if str != "" {
|
||||
str += "\n\n"
|
||||
}
|
||||
|
||||
str += "\treturn nil"
|
||||
str = strings.TrimPrefix(str, "\t")
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package template
|
||||
|
||||
const CounterExternalTemplate = `
|
||||
package ${VarDaoPackageName}
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"${VarDaoPackagePath}/internal"
|
||||
)
|
||||
|
||||
type ${VarDaoClassName} struct {
|
||||
*internal.${VarDaoClassName}
|
||||
}
|
||||
|
||||
func New${VarDaoClassName}(db *mongo.Database) *${VarDaoClassName} {
|
||||
return &${VarDaoClassName}{${VarDaoClassName}: internal.New${VarDaoClassName}(db)}
|
||||
}
|
||||
`
|
||||
|
||||
const CounterInternalTemplate = `
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
// 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"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type ${VarDaoClassName} struct {
|
||||
Columns *${VarDaoPrefixName}Columns
|
||||
Database *mongo.Database
|
||||
Collection *mongo.Collection
|
||||
}
|
||||
|
||||
type ${VarDaoPrefixName}Model struct {
|
||||
ID string ${SymbolBacktick}bson:"_id"${SymbolBacktick}
|
||||
Value int64 ${SymbolBacktick}bson:"value"${SymbolBacktick}
|
||||
}
|
||||
|
||||
type ${VarDaoPrefixName}Columns struct {
|
||||
ID string
|
||||
Value string
|
||||
}
|
||||
|
||||
var ${VarDaoVariableName}Columns = &${VarDaoPrefixName}Columns{
|
||||
ID: "_id",
|
||||
Value: "value",
|
||||
}
|
||||
|
||||
func New${VarDaoClassName}(db *mongo.Database) *${VarDaoClassName} {
|
||||
return &${VarDaoClassName}{
|
||||
Columns: ${VarDaoVariableName}Columns,
|
||||
Database: db,
|
||||
Collection: db.Collection("${VarCollectionName}"),
|
||||
}
|
||||
}
|
||||
|
||||
// Incr 自增值
|
||||
func (dao *${VarDaoClassName}) Incr(ctx context.Context, key string, incr ...int) (int64, error) {
|
||||
var (
|
||||
upsert = true
|
||||
returnDocument = options.After
|
||||
counter = &${VarDaoPrefixName}Model{}
|
||||
value = 1
|
||||
)
|
||||
|
||||
if len(incr) > 0 {
|
||||
if incr[0] == 0 {
|
||||
return 0, errors.New("invalid increment value")
|
||||
}
|
||||
value = incr[0]
|
||||
}
|
||||
|
||||
rst := dao.Collection.FindOneAndUpdate(ctx, bson.M{
|
||||
dao.Columns.ID: key,
|
||||
}, bson.M{"$inc": bson.M{
|
||||
dao.Columns.Value: value,
|
||||
}}, &options.FindOneAndUpdateOptions{
|
||||
Upsert: &upsert,
|
||||
ReturnDocument: &returnDocument,
|
||||
})
|
||||
|
||||
if err := rst.Decode(counter); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return counter.Value, nil
|
||||
}
|
||||
`
|
|
@ -0,0 +1,292 @@
|
|||
package template
|
||||
|
||||
const ExternalTemplate = `
|
||||
package ${VarDaoPackageName}
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"${VarDaoPackagePath}/internal"
|
||||
)
|
||||
|
||||
type ${VarDaoPrefixName}Columns = internal.${VarDaoPrefixName}Columns
|
||||
|
||||
type ${VarDaoClassName} struct {
|
||||
*internal.${VarDaoClassName}
|
||||
}
|
||||
|
||||
func New${VarDaoClassName}(db *mongo.Database, c *mongo.Collection) *${VarDaoClassName} {
|
||||
v := internal.New${VarDaoClassName}(nil)
|
||||
v.Database = db
|
||||
v.Collection = c
|
||||
panic("创建索引")
|
||||
//c.Indexes().CreateOne()
|
||||
//c.Indexes().CreateMany()
|
||||
return &${VarDaoClassName}{${VarDaoClassName}: v}
|
||||
}
|
||||
`
|
||||
|
||||
const InternalTemplate = `
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// 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 (
|
||||
${VarPackages}
|
||||
)
|
||||
|
||||
type ${VarDaoPrefixName}FilterFunc func(cols *${VarDaoPrefixName}Columns) interface{}
|
||||
type ${VarDaoPrefixName}UpdateFunc func(cols *${VarDaoPrefixName}Columns) interface{}
|
||||
type ${VarDaoPrefixName}PipelineFunc func(cols *${VarDaoPrefixName}Columns) interface{}
|
||||
type ${VarDaoPrefixName}CountOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.CountOptions
|
||||
type ${VarDaoPrefixName}AggregateOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.AggregateOptions
|
||||
type ${VarDaoPrefixName}FindOneOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.FindOneOptions
|
||||
type ${VarDaoPrefixName}FindManyOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.FindOptions
|
||||
type ${VarDaoPrefixName}UpdateOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.UpdateOptions
|
||||
type ${VarDaoPrefixName}DeleteOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.DeleteOptions
|
||||
type ${VarDaoPrefixName}InsertOneOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.InsertOneOptions
|
||||
type ${VarDaoPrefixName}InsertManyOptionsFunc func(cols *${VarDaoPrefixName}Columns) *options.InsertManyOptions
|
||||
|
||||
type ${VarDaoClassName} struct {
|
||||
Columns *${VarDaoPrefixName}Columns
|
||||
Database *mongo.Database
|
||||
Collection *mongo.Collection
|
||||
}
|
||||
|
||||
type ${VarDaoPrefixName}Columns struct {
|
||||
${VarModelColumnsDefine}
|
||||
}
|
||||
|
||||
var ${VarDaoVariableName}Columns = &${VarDaoPrefixName}Columns{
|
||||
${VarModelColumnsInstance}
|
||||
}
|
||||
|
||||
func New${VarDaoClassName}(db *mongo.Database) *${VarDaoClassName} {
|
||||
return &${VarDaoClassName}{
|
||||
Columns: ${VarDaoVariableName}Columns,
|
||||
Database: db,
|
||||
Collection: db.Collection("${VarCollectionName}"),
|
||||
}
|
||||
}
|
||||
|
||||
// Count returns the number of documents in the collection.
|
||||
func (dao *${VarDaoClassName}) Count(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, optionsFunc ...${VarDaoPrefixName}CountOptionsFunc) (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 *${VarDaoClassName}) Aggregate(ctx context.Context, pipelineFunc ${VarDaoPrefixName}PipelineFunc, optionsFunc ...${VarDaoPrefixName}AggregateOptionsFunc) (*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 *${VarDaoClassName}) InsertOne(ctx context.Context, model *${VarModelPackageName}.${VarModelClassName}, optionsFunc ...${VarDaoPrefixName}InsertOneOptionsFunc) (*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 *${VarDaoClassName}) InsertMany(ctx context.Context, models []*${VarModelPackageName}.${VarModelClassName}, optionsFunc ...${VarDaoPrefixName}InsertManyOptionsFunc) (*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 *${VarDaoClassName}) UpdateOne(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, updateFunc ${VarDaoPrefixName}UpdateFunc, optionsFunc ...${VarDaoPrefixName}UpdateOptionsFunc) (*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 *${VarDaoClassName}) UpdateOneByID(ctx context.Context, id string, updateFunc ${VarDaoPrefixName}UpdateFunc, optionsFunc ...${VarDaoPrefixName}UpdateOptionsFunc) (*mongo.UpdateResult, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.UpdateOne(ctx, func(cols *${VarDaoPrefixName}Columns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, updateFunc, optionsFunc...)
|
||||
}
|
||||
|
||||
// UpdateMany executes an update command to update documents in the collection.
|
||||
func (dao *${VarDaoClassName}) UpdateMany(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, updateFunc ${VarDaoPrefixName}UpdateFunc, optionsFunc ...${VarDaoPrefixName}UpdateOptionsFunc) (*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 *${VarDaoClassName}) FindOne(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, optionsFunc ...${VarDaoPrefixName}FindOneOptionsFunc) (*${VarModelPackageName}.${VarModelClassName}, error) {
|
||||
var (
|
||||
opts *options.FindOneOptions
|
||||
model = &${VarModelPackageName}.${VarModelClassName}{}
|
||||
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 *${VarDaoClassName}) FindOneByID(ctx context.Context, id string, optionsFunc ...${VarDaoPrefixName}FindOneOptionsFunc) (*${VarModelPackageName}.${VarModelClassName}, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.FindOne(ctx, func(cols *${VarDaoPrefixName}Columns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, optionsFunc...)
|
||||
}
|
||||
|
||||
// FindMany executes a find command and returns many models the matching documents in the collection.
|
||||
func (dao *${VarDaoClassName}) FindMany(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, optionsFunc ...${VarDaoPrefixName}FindManyOptionsFunc) ([]*${VarModelPackageName}.${VarModelClassName}, 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([]*${VarModelPackageName}.${VarModelClassName}, 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 *${VarDaoClassName}) DeleteOne(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, optionsFunc ...${VarDaoPrefixName}DeleteOptionsFunc) (*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 *${VarDaoClassName}) DeleteOneByID(ctx context.Context, id string, optionsFunc ...${VarDaoPrefixName}DeleteOptionsFunc) (*mongo.DeleteResult, error) {
|
||||
objectID, err := primitive.ObjectIDFromHex(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dao.DeleteOne(ctx, func(cols *${VarDaoPrefixName}Columns) interface{} {
|
||||
return bson.M{"_id": objectID}
|
||||
}, optionsFunc...)
|
||||
}
|
||||
|
||||
// DeleteMany executes a delete command to delete documents from the collection.
|
||||
func (dao *${VarDaoClassName}) DeleteMany(ctx context.Context, filterFunc ${VarDaoPrefixName}FilterFunc, optionsFunc ...${VarDaoPrefixName}DeleteOptionsFunc) (*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 *${VarDaoClassName}) autofill(ctx context.Context, model *${VarModelPackageName}.${VarModelClassName}) error {
|
||||
${VarAutofillCode}
|
||||
}
|
||||
`
|
|
@ -0,0 +1,160 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type style string
|
||||
|
||||
const (
|
||||
kebabCase style = "kebab" // 全小写中划线
|
||||
underscoreCase style = "underscore" // 小写下划线
|
||||
camelCase style = "camel" // 小写字母开头驼峰
|
||||
pascalCase style = "pascal" // 大写字母开头驼峰
|
||||
lowerCase style = "lower" // 全小写
|
||||
)
|
||||
|
||||
// convert to underscore style, example: UserProfile > user_profile
|
||||
func toUnderscoreCase(s string) string {
|
||||
return toLowerCase(s, 95)
|
||||
}
|
||||
|
||||
// convert to kebab style, example: UserProfile > user-profile
|
||||
func toKebabCase(s string) string {
|
||||
return toLowerCase(s, 45)
|
||||
}
|
||||
|
||||
// convert to camel style, example: user-profile > userProfile
|
||||
func toCamelCase(s string) string {
|
||||
chars := make([]rune, 0, len(s))
|
||||
upper := false
|
||||
first := true
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch {
|
||||
case s[i] >= 65 && s[i] <= 90:
|
||||
if first {
|
||||
chars = append(chars, rune(s[i]+32))
|
||||
} else {
|
||||
chars = append(chars, rune(s[i]))
|
||||
}
|
||||
first = false
|
||||
upper = false
|
||||
case s[i] >= 97 && s[i] <= 122:
|
||||
if upper && !first {
|
||||
chars = append(chars, rune(s[i]-32))
|
||||
} else {
|
||||
chars = append(chars, rune(s[i]))
|
||||
}
|
||||
first = false
|
||||
upper = false
|
||||
case s[i] == 45:
|
||||
upper = true
|
||||
case s[i] == 95:
|
||||
upper = true
|
||||
}
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
||||
// convert to pascal style, example: user-profile > UserProfile
|
||||
func toPascalCase(s string) string {
|
||||
s = toCamelCase(s)
|
||||
return strings.ToUpper(string(s[0])) + s[1:]
|
||||
}
|
||||
|
||||
func toLowerCase(s string, c rune) string {
|
||||
chars := make([]rune, 0)
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= 65 && s[i] <= 90 {
|
||||
if i == 0 {
|
||||
chars = append(chars, rune(s[i]+32))
|
||||
} else {
|
||||
chars = append(chars, c, rune(s[i]+32))
|
||||
}
|
||||
} else {
|
||||
chars = append(chars, rune(s[i]))
|
||||
}
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
||||
func toPackageName(s string) string {
|
||||
chars := make([]rune, 0, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch {
|
||||
case s[i] >= 65 && s[i] <= 90:
|
||||
chars = append(chars, rune(s[i]+32))
|
||||
case s[i] >= 97 && s[i] <= 122:
|
||||
chars = append(chars, rune(s[i]))
|
||||
}
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
||||
func toPackagePath(s string, style style) string {
|
||||
switch style {
|
||||
case kebabCase:
|
||||
return toKebabCase(s)
|
||||
case underscoreCase:
|
||||
return toUnderscoreCase(s)
|
||||
case camelCase:
|
||||
return toCamelCase(s)
|
||||
case pascalCase:
|
||||
return toPascalCase(s)
|
||||
case lowerCase:
|
||||
return toPackageName(s)
|
||||
default:
|
||||
return toKebabCase(s)
|
||||
}
|
||||
}
|
||||
|
||||
func toFileName(s string, style style) string {
|
||||
switch style {
|
||||
case kebabCase:
|
||||
return toKebabCase(s)
|
||||
case underscoreCase:
|
||||
return toUnderscoreCase(s)
|
||||
case camelCase:
|
||||
return toCamelCase(s)
|
||||
case pascalCase:
|
||||
return toPascalCase(s)
|
||||
case lowerCase:
|
||||
return toPackageName(s)
|
||||
default:
|
||||
return toUnderscoreCase(s)
|
||||
}
|
||||
}
|
||||
|
||||
func doWrite(file string, tpl string, replaces map[string]string) error {
|
||||
s := os.Expand(tpl, func(s string) string {
|
||||
switch {
|
||||
case len(s) >= 3 && s[:3] == "Var":
|
||||
return replaces[s]
|
||||
case len(s) >= 6 && s[:6] == "Symbol":
|
||||
return replaces[s]
|
||||
default:
|
||||
return "$" + s
|
||||
}
|
||||
})
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(file, []byte(strings.TrimPrefix(s, "\n")), os.ModePerm)
|
||||
}
|
||||
|
||||
// 大写字母开头的字段才是导出的
|
||||
func isExportable(s string) bool {
|
||||
r, _ := utf8.DecodeRuneInString(s)
|
||||
return unicode.IsUpper(r)
|
||||
}
|
Loading…
Reference in New Issue