You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zero/tools/goctl/model/mongo
anqiansong 5383e29ce6
feat: Replace cli to cobra (#1855)
* Replace cli

* Replace cli

* Replace cli

* Format code

* Add compare case

* Add compare case

* Add compare case

* Support go style flag

* Support go style flag

* Add test case
3 years ago
..
generate feat: Replace cli to cobra (#1855) 3 years ago
template feat: use go:embed to embed templates (#1756) 3 years ago
mongo.go feat: Replace cli to cobra (#1855) 3 years ago
readme.md chore: update command comment (#1501) 3 years ago

readme.md

mongo生成model

背景

在业务务开发中model(dao)数据访问层是一个服务必不可缺的一层因此数据库访问的CURD也是必须要对外提供的访问方法 而CURD在go-zero中就仅存在两种情况

  • 带缓存model
  • 不带缓存model

从代码结构上来看C-U-R-D四个方法就是固定的结构因此我们可以将其交给goctl工具去完成帮助我们提升开发效率。

方案设计

mongo的生成不同于mysqlmysql可以从scheme_information库中读取到一张表的信息字段名称数据类型索引等 而mongo是文档型数据库我们暂时无法从db中读取某一条记录来实现字段信息获取就算有也不一定是完整信息某些字段可能是omitempty修饰可有可无 这里采用type自己编写+代码生成方式实现

使用示例

假设我们需要生成一个usermodel.go的代码文件其包含用户信息字段有

字段名称 字段类型
_id bson.ObejctId
name string

编写types.go

$ vim types.go
package model

//go:generate goctl model mongo -t User
import "github.com/globalsign/mgo/bson"

type User struct {
	ID   bson.ObjectId `bson:"_id"`
	Name string        `bson:"name"`
}

生成代码

生成代码的方式有两种

  • 命令行生成 在types.go所在文件夹执行命令
    $ goctl model mongo -t User -style gozero
    
  • 在types.go中添加//go:generate,然后点击执行按钮即可生成,内容示例如下:
    //go:generate goctl model mongo -t User
    

生成示例代码

  • usermodel.go

    package model
    
    import (
        "context"
    
        "github.com/globalsign/mgo/bson"
        cachec "github.com/zeromicro/go-zero/core/stores/cache"
        "github.com/zeromicro/go-zero/core/stores/mongoc"
    )
    
    type UserModel interface {
        Insert(data *User, ctx context.Context) error
        FindOne(id string, ctx context.Context) (*User, error)
        Update(data *User, ctx context.Context) error
        Delete(id string, ctx context.Context) error
    }
    
    type defaultUserModel struct {
        *mongoc.Model
    }
    
    func NewUserModel(url, collection string, c cachec.CacheConf) UserModel {
        return &defaultUserModel{
            Model: mongoc.MustNewModel(url, collection, c),
        }
    }
    
    func (m *defaultUserModel) Insert(data *User, ctx context.Context) error {
        if !data.ID.Valid() {
            data.ID = bson.NewObjectId()
        }
    
        session, err := m.TakeSession()
        if err != nil {
            return err
        }
    
        defer m.PutSession(session)
        return m.GetCollection(session).Insert(data)
    }
    
    func (m *defaultUserModel) FindOne(id string, ctx context.Context) (*User, error) {
        if !bson.IsObjectIdHex(id) {
            return nil, ErrInvalidObjectId
        }
    
        session, err := m.TakeSession()
        if err != nil {
            return nil, err
        }
    
        defer m.PutSession(session)
        var data User
    
        err = m.GetCollection(session).FindOneIdNoCache(&data, bson.ObjectIdHex(id))
        switch err {
        case nil:
            return &data, nil
        case mongoc.ErrNotFound:
            return nil, ErrNotFound
        default:
            return nil, err
        }
    }
    
    func (m *defaultUserModel) Update(data *User, ctx context.Context) error {
        session, err := m.TakeSession()
        if err != nil {
            return err
        }
    
        defer m.PutSession(session)
    
        return m.GetCollection(session).UpdateIdNoCache(data.ID, data)
    }
    
    func (m *defaultUserModel) Delete(id string, ctx context.Context) error {
        session, err := m.TakeSession()
        if err != nil {
            return err
        }
    
        defer m.PutSession(session)
    
        return m.GetCollection(session).RemoveIdNoCache(bson.ObjectIdHex(id))
    }
    
  • error.go

    package model
    
    import "errors"
    
    var ErrNotFound = errors.New("not found")
    var ErrInvalidObjectId = errors.New("invalid objectId")
    

文件目录预览

.
├── error.go
├── types.go
└── usermodel.go

命令预览

NAME:
   goctl model - generate model code

USAGE:
   goctl model command [command options] [arguments...]

COMMANDS:
   mysql  generate mysql model
   mongo  generate mongo model

OPTIONS:
   --help, -h  show help
NAME:
   goctl model mongo - generate mongo model

USAGE:
   goctl model mongo [command options] [arguments...]

OPTIONS:
   --type value, -t value  specified model type name
   --cache, -c             generate code with cache [optional]
   --dir value, -d value   the target dir
   --style value           the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]

温馨提示

--type 支持slice传值示例 goctl model mongo -t=User -t=Class

注意事项

types.go本质上与xxxmodel.go无关只是将type定义部分交给开发人员自己编写了在xxxmodel.go中mongo文档的存储结构必须包含 _id字段对应到types中的field为IDmodel中的findOne,update均以data.ID来进行操作的当然如果不符合你的命名风格你也 可以修改模板,只要保证id 在types中的field名称和模板中一致就行。