feat: Replace mongo package with monc & mon (#2002)

* Replace mongo package with monc & mon

* Add terminal whitespace

* format code
This commit is contained in:
anqiansong
2022-06-12 23:02:34 +08:00
committed by GitHub
parent ed1c937998
commit c27e00b45c
16 changed files with 544 additions and 255 deletions

View File

@@ -15,196 +15,194 @@ mongo的生成不同于mysqlmysql可以从scheme_information库中读取到
而mongo是文档型数据库我们暂时无法从db中读取某一条记录来实现字段信息获取就算有也不一定是完整信息某些字段可能是omitempty修饰可有可无 这里采用type自己编写+代码生成方式实现
## 使用示例
假设我们需要生成一个usermodel.go的代码文件其包含用户信息字段有
|字段名称|字段类型|
|---|---|
|_id|bson.ObejctId|
|name|string|
### 编写types.go
```shell
$ vim types.go
为 User 生成 mongo model
```bahs
$ goctl model mongo -t User -c --dir .
```
```golang
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所在文件夹执行命令
```shell
$ goctl model mongo -t User -style gozero
```
* 在types.go中添加`//go:generate`,然后点击执行按钮即可生成,内容示例如下:
```golang
//go:generate goctl model mongo -t User
```
### 生成示例代码
* usermodel.go
#### usermodel.go
```go
package model
```golang
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))
}
```
import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/monc"
)
* error.go
var _ UserModel = (*customUserModel)(nil)
```golang
package model
type (
// UserModel is an interface to be customized, add more methods here,
// and implement the added methods in customUserModel.
UserModel interface {
userModel
}
import "errors"
var ErrNotFound = errors.New("not found")
var ErrInvalidObjectId = errors.New("invalid objectId")
```
customUserModel struct {
*defaultUserModel
}
)
// NewUserModel returns a model for the mongo.
func NewUserModel(url, db, collection string, c cache.CacheConf) UserModel {
conn := monc.MustNewModel(url, db, collection, c)
return &customUserModel{
defaultUserModel: newDefaultUserModel(conn),
}
}
```
#### usermodelgen.go
```go
// Code generated by goctl. DO NOT EDIT!
package model
import (
"context"
"time"
"github.com/zeromicro/go-zero/core/stores/monc"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var prefixUserCacheKey = "cache:user:"
type userModel interface {
Insert(ctx context.Context, data *User) error
FindOne(ctx context.Context, id string) (*User, error)
Update(ctx context.Context, data *User) error
Delete(ctx context.Context, id string) error
}
type defaultUserModel struct {
conn *monc.Model
}
func newDefaultUserModel(conn *monc.Model) *defaultUserModel {
return &defaultUserModel{conn: conn}
}
func (m *defaultUserModel) Insert(ctx context.Context, data *User) error {
if !data.ID.IsZero() {
data.ID = primitive.NewObjectID()
data.CreateAt = time.Now()
data.UpdateAt = time.Now()
}
key := prefixUserCacheKey + data.ID.Hex()
_, err := m.conn.InsertOne(ctx, key, data)
return err
}
func (m *defaultUserModel) FindOne(ctx context.Context, id string) (*User, error) {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, ErrInvalidObjectId
}
var data User
key := prefixUserCacheKey + data.ID.Hex()
err = m.conn.FindOne(ctx, key, &data, bson.M{"_id": oid})
switch err {
case nil:
return &data, nil
case monc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserModel) Update(ctx context.Context, data *User) error {
data.UpdateAt = time.Now()
key := prefixUserCacheKey + data.ID.Hex()
_, err := m.conn.ReplaceOne(ctx, key, bson.M{"_id": data.ID}, data)
return err
}
func (m *defaultUserModel) Delete(ctx context.Context, id string) error {
oid, err := primitive.ObjectIDFromHex(id)
if err != nil {
return ErrInvalidObjectId
}
key := prefixUserCacheKey + id
_, err = m.conn.DeleteOne(ctx, key, bson.M{"_id": oid})
return err
}
```
#### usertypes.go
```go
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type User struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
// TODO: Fill your own fields
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
}
```
#### error.go
```go
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
```
### 文件目录预览
```text
.
├── error.go
├── types.go
── usermodel.go
├── usermodel.go
── usermodelgen.go
└── usertypes.go
```
## 命令预览
```text
NAME:
goctl model - generate model code
Generate mongo model
USAGE:
goctl model command [command options] [arguments...]
Usage:
goctl model mongo [flags]
COMMANDS:
mysql generate mysql model
mongo generate mongo model
OPTIONS:
--help, -h show help
```
```text
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]
Flags:
--branch string The branch of the remote repo, it does work with --remote
-c, --cache Generate code with cache [optional]
-d, --dir string The target dir
-h, --help help for mongo
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
-t, --type strings Specified model type name
```
> 温馨提示
>
> `--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名称和模板中一致就行。