英文:
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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论