如何为Go mongo-driver的FindOptions编写链式包装函数及MergeFindOptions用法
问题解答
一、链式调用包装方案(完全可行)
你可以通过自定义结构体封装mongo.FindOptions,对外暴露链式调用的方法,服务层只需导入你的封装包,无需直接依赖go.mongodb.org/mongo-driver/mongo/options。
实现代码示例
// 假设你的封装包为 internal/dbobject package dbobject import ( "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson" ) // FindOpt 封装mongo.FindOptions,对外提供链式调用接口 type FindOpt struct { opt *options.FindOptions } // NewFindOpt 创建一个空的FindOpt实例 func NewFindOpt() *FindOpt { return &FindOpt{ opt: options.Find(), } } // SetSkip 设置跳过的文档数量,返回自身实现链式调用 func (f *FindOpt) SetSkip(skip int64) *FindOpt { f.opt.SetSkip(skip) return f } // SetLimit 设置返回的文档数量上限,返回自身实现链式调用 func (f *FindOpt) SetLimit(limit int64) *FindOpt { f.opt.SetLimit(limit) return f } // SetSort 设置排序规则,返回自身实现链式调用 func (f *FindOpt) SetSort(sort interface{}) *FindOpt { // 支持直接传入bson.D或map等排序参数 f.opt.SetSort(sort) return f } // GetOptions 返回底层的FindOptions,供内部MongoDB操作使用 func (f *FindOpt) GetOptions() *options.FindOptions { return f.opt }
服务层调用示例
服务层无需导入options包,直接使用你的封装类型:
package service import "your-project-path/internal/dbobject" import "go.mongodb.org/mongo-driver/bson" func GetUsers(page, pageSize int64) ([]User, error) { // 链式调用设置分页和排序 opt := dbobject.NewFindOpt(). SetSkip((page - 1) * pageSize). SetLimit(pageSize). SetSort(bson.D{{Key: "created_at", Value: -1}}) // 传递给你的DB操作函数(内部调用GetOptions()拿到原生FindOptions) return db.FindUsers(opt.GetOptions()) }
二、MergeFindOptions 用法与示例
options.MergeFindOptions的作用是将多个*options.FindOptions实例合并为一个,后传入的选项会覆盖先传入的同名配置(比如两个选项都设置了Skip,最终取最后一个的值)。
基础用法示例
package dbobject import ( "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/bson" ) func MergeExample() *options.FindOptions { // 创建基础选项:设置默认分页 baseOpt := options.Find().SetSkip(0).SetLimit(10) // 创建自定义选项:覆盖Skip,新增排序 customOpt := options.Find().SetSkip(20).SetSort(bson.D{{Key: "id", Value: 1}}) // 合并选项:customOpt的配置会覆盖baseOpt的同名项 mergedOpt := options.MergeFindOptions(baseOpt, customOpt) // 最终mergedOpt的Skip为20,Limit为10,Sort为按id升序 return mergedOpt }
结合自定义封装的示例
如果你想在封装中支持合并逻辑,可以新增一个方法:
// Merge 合并其他FindOpt的配置到当前实例 func (f *FindOpt) Merge(other *FindOpt) *FindOpt { f.opt = options.MergeFindOptions(f.opt, other.opt) return f } // 调用示例 func DemoMerge() { defaultOpt := dbobject.NewFindOpt().SetLimit(10) userOpt := dbobject.NewFindOpt().SetSkip(5).SetSort(bson.D{{Key: "name", Value: 1}}) // 合并后:Limit保持10,Skip为5,Sort生效 merged := defaultOpt.Merge(userOpt) }
内容的提问来源于stack exchange,提问作者Gopher_k
相关产品推荐
相关产品推荐

