MongoDB
MongoDB
Section titled “MongoDB”go-zero 封装了官方 mongo-driver,提供连接管理与可观测性支持。
Mongo: Uri: "mongodb://127.0.0.1:27017" Database: myapp在 Config 结构体中声明:
type Config struct { rest.RestConf Mongo struct { Uri string Database string }}import "github.com/zeromicro/go-zero/core/stores/mongo"
func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ Config: c, ArticleMod: mongo.MustNewModel(c.Mongo.Uri, c.Mongo.Database, "articles"), }}article := &Article{Title: "Hello go-zero", Content: "...", Published: false}result, err := l.svcCtx.ArticleMod.InsertOne(l.ctx, article)if err != nil { return nil, err}// result.InsertedID 为新文档的 _idvar article Articleerr := l.svcCtx.ArticleMod.FindOne(l.ctx, bson.M{"_id": id}, &article)if errors.Is(err, mongo.ErrNotFound) { return nil, errorx.ErrNotFound}var articles []Articleerr := l.svcCtx.ArticleMod.FindAll(l.ctx, bson.M{"published": true}, &articles)限制条数与排序:
opts := options.Find().SetLimit(20).SetSort(bson.D{{Key: "createdAt", Value: -1}})err := l.svcCtx.ArticleMod.FindAllWithOptions(l.ctx, bson.M{}, &articles, opts)使用 $set 更新指定字段:
filter := bson.M{"_id": id}update := bson.M{"$set": bson.M{"title": "已更新", "updatedAt": time.Now()}}result, err := l.svcCtx.ArticleMod.UpdateOne(l.ctx, filter, update)// result.MatchedCount / result.ModifiedCountUpsert(不存在则插入):
opts := options.Update().SetUpsert(true)_, err = l.svcCtx.ArticleMod.UpdateOneWithOptions(l.ctx, filter, update, opts)// 删除单条result, err := l.svcCtx.ArticleMod.DeleteOne(l.ctx, bson.M{"_id": id})
// 删除多条result, err := l.svcCtx.ArticleMod.DeleteMany(l.ctx, bson.M{"published": false})// result.DeletedCountcount, err := l.svcCtx.ArticleMod.CountDocuments(l.ctx, bson.M{"published": true})pipeline := mongo.Pipeline{ {{Key: "$match", Value: bson.M{"published": true}}}, {{Key: "$group", Value: bson.M{ "_id": "$authorId", "total": bson.M{"$sum": 1}, }}}, {{Key: "$sort", Value: bson.M{"total": -1}}}, {{Key: "$limit", Value: 10}},}
var results []bson.Merr := l.svcCtx.ArticleMod.Aggregate(l.ctx, pipeline, &results)将 model 封装为带类型的仓储,使 logic 代码更清晰:
type ArticleModel interface { Insert(ctx context.Context, article *Article) error FindById(ctx context.Context, id primitive.ObjectID) (*Article, error) ListPublished(ctx context.Context, limit int64) ([]Article, error) Delete(ctx context.Context, id primitive.ObjectID) error}
type defaultArticleModel struct { mod *mongo.Model}
func NewArticleModel(uri, db string) ArticleModel { return &defaultArticleModel{mod: mongo.MustNewModel(uri, db, "articles")}}
func (m *defaultArticleModel) FindById(ctx context.Context, id primitive.ObjectID) (*Article, error) { var a Article if err := m.mod.FindOne(ctx, bson.M{"_id": id}, &a); err != nil { return nil, err } return &a, nil}