英文:
creating a filter with pagination with golang for MongoDB
问题
我有一个大型过滤器,并且我将提供其中的一部分代码。我试图通过分页传递过滤器的映射,但是我遇到了一个错误,错误信息如下:
the match filter must be an expression in an object
获取过滤器的代码如下:
func (app *Courses) getFilter(filter *Filter) ([]bson.M, error) {
pipeline := make([]bson.M, 0)
if filter.All {
// 包含所有项目
} else {
// 根据提供的条件过滤项目
if filter.Beginner {
pipeline = append(pipeline, bson.M{"tags": "beginner"})
}
if filter.Advanced {
pipeline = append(pipeline, bson.M{"tags": "advanced"})
}
if filter.Go {
pipeline = append(pipeline, bson.M{"tags": "go"})
}
}
return pipeline, nil
}
处理程序代码如下:
func (app *Courses) CoursesAllHandler(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
clog := log.GetLoggerFromContext(ctx)
p := r.URL.Query().Get("page")
ps := r.URL.Query().Get("pageSize")
var filter Filter
err := json.NewDecoder(r.Body).Decode(&filter)
if err != nil {
http.Error(w, "Failed to parse request body", http.StatusBadRequest)
return
}
pipeline := make([]bson.M, 0)
page, _ := strconv.Atoi(p)
pageSize, _ := strconv.Atoi(ps)
// 分页
skip := (page - 1) * pageSize
limit := pageSize
// 添加过滤器
pipeline, err = app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline = append(pipeline, bson.M{"$match": pipeline})
// 添加分页阶段到管道中
pipeline = append(pipeline, bson.M{"$skip": skip})
pipeline = append(pipeline, bson.M{"$limit": limit})
res, err := app.repo.GetAll(ctx, pipeline)
if err != nil {
clog.Error(err)
return
}
err = app.helper.WriteJSON(w, http.StatusOK, envelope{"data": res, "metadata": "none"}, nil)
if err != nil {
clog.ErrorCtx(err, log.Ctx{
"header": w.Header(),
"request_url": r.URL.String(),
})
}
}
我如何获取设置为"true"或"false"的值,将它们放入映射中,并将其提交到查询中以与数据库匹配,就像我在这里尝试做的那样:
// 添加过滤器
pipeline, err = app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline = append(pipeline, bson.M{"$match": pipeline})
更新:
现在我有以下代码:
func (app *Courses) CoursesAllHandler(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
clog := log.GetLoggerFromContext(ctx)
var filter Filter
err := json.NewDecoder(r.Body).Decode(&filter)
if err != nil {
http.Error(w, "Failed to parse request body", http.StatusBadRequest)
return
}
filter.All = true
pipeline := make([]bson.M, 3)
// 添加过滤器
matches, err := app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline[0] = bson.M{"$skip": 1}
pipeline[1] = bson.M{"$limit": 5}
pipeline[2] = bson.M{"$match": matches}
res, err := app.repo.GetAll(ctx, pipeline)
if err != nil {
clog.Error(err)
return
}
err = app.helper.WriteJSON(w, http.StatusOK, envelope{"data": res, "metadata": "none"}, nil)
if err != nil {
clog.ErrorCtx(err, log.Ctx{
"header": w.Header(),
"request_url": r.URL.String(),
})
}
}
过滤器的代码如下:
func (app *Courses) getFilter(filter *Filter) (bson.M, error) {
match := bson.M{}
tags := []string{}
if filter.All {
// 包含所有项目
tags = append(tags, "beginner")
tags = append(tags, "intermediate")
......
} else {
// 根据提供的条件过滤项目
if filter.Beginner {
tags = append(tags, "beginner")
}
if filter.Advanced {
tags = append(tags, "advanced")
}
if filter.Go {
tags = append(tags, "go")
}
........
}
match = bson.M{
"tags": bson.M{"$in": tags},
}
return match, nil
}
然后在这里使用:
func (r *CourseRepo) GetAll(ctx context.Context, pipeline []bson.M) ([]Course, error) {
clog := log.GetLoggerFromContext(ctx)
cur, err := r.collection.Aggregate(ctx, pipeline)
...
然而,它是空的。在过滤器中选择了所有内容,并且没有错误。
英文:
I have a large filter and I will provide a snippet of it. I am trying to pass a map of the filter with paganization but I get an error that reads
the match filter must be an expression in an object
getting the filter
func (app *Courses) getFilter(filter *Filter) ([]bson.M, error) {
pipeline := make([]bson.M, 0)
if filter.All {
// Include all items
} else {
// Filter items based on the provided criteria
if filter.Beginner {
pipeline = append(pipeline, bson.M{"tags": "beginner"})
}
if filter.Advanced {
pipeline = append(pipeline, bson.M{"tags": "advanced"})
}
if filter.Go {
pipeline = append(pipeline, bson.M{"tags": "go"})
}
}
return pipeline, nil
}
Handler
func (app *Courses) CoursesAllHandler(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
clog := log.GetLoggerFromContext(ctx)
p := r.URL.Query().Get("page")
ps := r.URL.Query().Get("pageSize")
var filter Filter
err := json.NewDecoder(r.Body).Decode(&filter)
if err != nil {
http.Error(w, "Failed to parse request body", http.StatusBadRequest)
return
}
pipeline := make([]bson.M, 0)
page, _ := strconv.Atoi(p)
pageSize, _ := strconv.Atoi(ps)
// Pagination
skip := (page - 1) * pageSize
limit := pageSize
// Add filter
pipeline, err = app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline = append(pipeline, bson.M{"$match": pipeline})
// Add pagination stages to the pipeline
pipeline = append(pipeline, bson.M{"$skip": skip})
pipeline = append(pipeline, bson.M{"$limit": limit})
res, err := app.repo.GetAll(ctx, pipeline)
if err != nil {
clog.Error(err)
return
}
err = app.helper.WriteJSON(w, http.StatusOK, envelope{"data": res, "metadata": "none"}, nil)
if err != nil {
clog.ErrorCtx(err, log.Ctx{
"header": w.Header(),
"request_url": r.URL.String(),
})
}
}
How can I get the values set "true" or "false", put them in a map and submit them in the query to be matched the DB like I am trying to do here.
// Add filter
pipeline, err = app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline = append(pipeline, bson.M{"$match": pipeline})
---- update ----
I now have:
func (app *Courses) CoursesAllHandler(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
clog := log.GetLoggerFromContext(ctx)
var filter Filter
err := json.NewDecoder(r.Body).Decode(&filter)
if err != nil {
http.Error(w, "Failed to parse request body", http.StatusBadRequest)
return
}
filter.All = true
pipeline := make([]bson.M, 3)
// Add filter
matches, err := app.getFilter(&filter)
if err != nil {
clog.Error(err)
}
pipeline[0] = bson.M{"$skip": 1}
pipeline[1] = bson.M{"$limit": 5}
pipeline[2] = bson.M{"$match": matches}
res, err := app.repo.GetAll(ctx, pipeline)
if err != nil {
clog.Error(err)
return
}
err = app.helper.WriteJSON(w, http.StatusOK, envelope{"data": res, "metadata": "none"}, nil)
if err != nil {
clog.ErrorCtx(err, log.Ctx{
"header": w.Header(),
"request_url": r.URL.String(),
})
}
}
and the filter looks like
func (app *Courses) getFilter(filter *Filter) (bson.M, error) {
match := bson.M{}
tags := []string{}
if filter.All {
// Include all items
tags = append(tags, "beginner")
tags = append(tags, "intermediate")
.....
} else {
// Filter items based on the provided criteria
if filter.Beginner {
tags = append(tags, "beginner")
}
if filter.Advanced {
tags = append(tags, "advanced")
}
if filter.Go {
tags = append(tags, "go")
}
........
}
match = bson.M{
"tags": bson.M{"$in": tags},
}
return match, nil
}
which is later used here..
func (r *CourseRepo) GetAll(ctx context.Context, pipeline []bson.M) ([]Course, error) {
clog := log.GetLoggerFromContext(ctx)
cur, err := r.collection.Aggregate(ctx, pipeline)
...
However it is empty. Everything is selected in the filter and there is no error.
答案1
得分: 2
你遇到了the match filter must be an expression in an object
的错误,这是因为$match
期望一个对象(bson.M
),但你提供了一个对象的切片([]bson.M
)。
尝试使用以下代码:
func (app *Courses) getFilter(filter *Filter) (bson.M, error) {
match := bson.M{}
tags := []string{}
if filter.All {
// 包含所有项目
} else {
// 根据提供的条件筛选项目
if filter.Beginner {
tags = append(tags, "beginner")
}
if filter.Advanced {
tags = append(tags, "advanced")
}
if filter.Go {
tags = append(tags, "go")
}
match = bson.M{
"tags": bson.M{"$in": tags},
}
}
return match, nil
}
希望对你有帮助!
英文:
You are getting the match filter must be an expression in an object
because the $match
expecting an object (bson.M
) but you have given slice of objects ([]bson.M)
.
Try this
func (app *Courses) getFilter(filter *Filter) (bson.M, error) {
match := bson.M{}
tags := []string{}
if filter.All {
// Include all items
} else {
// Filter items based on the provided criteria
if filter.Beginner {
tags = append(tags, "beginner")
}
if filter.Advanced {
tags = append(tags, "advanced")
}
if filter.Go {
tags = append(tags, "go")
}
match = bson.M{
"tags": bson.M{"$in": tags},
}
}
return match, nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论