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.
5383e29ce6
* 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 | 3 years ago | |
template | 3 years ago | |
mongo.go | 3 years ago | |
readme.md | 3 years ago |
readme.md
mongo生成model
背景
在业务务开发中,model(dao)数据访问层是一个服务必不可缺的一层,因此数据库访问的CURD也是必须要对外提供的访问方法, 而CURD在go-zero中就仅存在两种情况
- 带缓存model
- 不带缓存model
从代码结构上来看,C-U-R-D四个方法就是固定的结构,因此我们可以将其交给goctl工具去完成,帮助我们提升开发效率。
方案设计
mongo的生成不同于mysql,mysql可以从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为ID
,model中的findOne,update均以data.ID来进行操作的,当然,如果不符合你的命名风格,你也 可以修改模板,只要保证id
在types中的field名称和模板中一致就行。