使用Golang为MongoDB创建带有分页功能的过滤器。

huangapple go评论88阅读模式
英文:

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
}

huangapple
  • 本文由 发表于 2023年7月17日 13:55:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701804.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定