Sort mongo results if a value exists in the field or not

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

Sort mongo results if a value exists in the field or not

问题

我有一个名为Student的结构体,看起来像这样。

type Student struct {
    Name     string   `json:"name" bson:"name"`
    Marks    int      `json:"marks" bson:"marks"`
    Subjects []string `json:"subjects" bson:"subjects"`
}

我正在使用opts.Sort来对结果进行排序。更多信息请参考以下代码。

opts.Sort = bson.D{
    {Key: "marks", Value: -1},
}

我还想按照Subjects对结果进行排序,如果对于任何一个学生,存在Math这个科目,那么它应该在排序时排在前面(降序),然后再按照marks进行排序。

我尝试了以下代码:

opts.Sort = bson.D{
    {Key: "subjects", Value: bson.M{"$in": "math"}},
    {Key: "marks", Value: -1},
}

我知道这看起来不对,因为我没有传递1或-1,但我不知道如何修改它使其正常工作。我在这里漏掉了什么?

英文:

I have a Student struct which looks like this.

type Student struct {
	Name            string                         `json:"name" bson:"name"`
	Marks           int                            `json:"marks" bson:"marks"`
	Subjects        []string                       `json:"subjects" bson:"subjects"`
}

I am using opts.Sort to Sort the result. More on that

opts.Sort = bson.D{
	{Key: "marks", Value: -1},
}

I also want to sort the results by Subjects, in a way that, if for any Student, if the subject Math exist, it should be sorted on top (descending order), before sorting it by marks
I tried doing this

opts.Sort = bson.D{
    {Key: "subjects", Value: bson.M{"$in": "math"}},
	{Key: "marks", Value: -1},
}

I know this doesn't seem right because I am not passing 1 or -1 but I don't know how can I modify it to make it work.
What am I missing here?.

答案1

得分: 1

你不能通过单个“简单”的查询来实现这个。

首先按marks字段查询记录,并在Go中进行第二次排序,将具有“math”科目的文档移到前面。

如果你只需要在MongoDB中完成这个操作,你可以重新设计:例如,你可以在文档中添加一个布尔字段,存储学生是否有“math”的信息,这样你就可以轻松地将其包含在排序中。

但请注意,你可以使用聚合框架来实现这个。以下是可以实现你需求的查询:

db.students.aggregate(
    {$addFields:{"hasMath": {$in:["math", "$subjects"]}}},
    {$sort:{"hasMath": -1, "marks": -1}}
)

这个查询的实质就是我建议的:它添加了一个hasMath字段,告诉我们学生的subjects数组中是否有“math”,然后首先按hasMath降序,然后按照marks降序排序文档。

以下是使用官方的mongo-go驱动在Go中实现的方法:

c := ... // 获取students集合

pipe := []bson.M{
	{"$addFields": bson.M{
		"hasMath": bson.M{"$in": []interface{}{"math", "$subjects"}},
	}},
	{"$sort": bson.D{
		{Key: "hasMath", Value: -1},
		{Key: "marks", Value: -1},
	}},
}

curs, err := c.Aggregate(ctx, pipe)
if err != nil {
	// 处理错误
	panic(err)
}

var students []Student
if err := curs.All(ctx, &students); err != nil {
	// 处理错误
	panic(err)
}
英文:

You can't do this with a single "simple" query.

Query the records sorted by marks, and do a second sorting in Go, by moving documents having "math" subject to the front.

If you need to do this only in MongoDB, you may redesign: e.g. you may add a boolean field to documents storing the information whether the student has "math", so you can easily include that in sorting.

Do note however that you may do this with the Aggregation framework. This is the query that would do what you need:

db.students.aggregate(
    {$addFields:{"hasMath": {$in:["math", "$subjects"]}}},
    {$sort:{hasMath: -1, marks: -1}}
)

What this does is essentially what I suggested: it adds a hasMath field, telling if the student has "math" in the subjects array, and then sorts documents first by hasMath descending, then by marks descending.

This is how you can do that in Go using the official mongo-go driver:

c := ... // Obtain students collection

pipe := []bson.M{
	{"$addFields": bson.M{
		"hasMath": bson.M{"$in": []any{"math", "$subjects"}},
	}},
	{"$sort": bson.D{
		{Key: "hasMath", Value: -1},
		{Key: "marks", Value: -1},
	}},
}

curs, err := c.Aggregate(ctx, pipe)
if err != nil {
	// Handle error
	panic(err)
}

var students []Student
if err := curs.All(ctx, &students); err != nil {
	// Handle error
	panic(err)
}

huangapple
  • 本文由 发表于 2023年1月18日 23:43:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75161764.html
匿名

发表评论

匿名网友

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

确定