Mongodb 找出最高的两次考试成绩
Mongodb find the highest two exams scores
我有一个学生合集,如下所示:
如何找到每个学生最多两个考试成绩
[
{
"_id" : ObjectId("61868aa03b2fe72b58c891a5"),
"name" : "Max",
"examScores" : [
{
"difficulty" : 4,
"score" : 57.9
},
{
"difficulty" : 6,
"score" : 62.1
},
{
"difficulty" : 3,
"score" : 88.5
}
]
},
{
"_id" : ObjectId("61868aa03b2fe72b58c891a6"),
"name" : "Manu",
"examScores" : [
{
"difficulty" : 7,
"score" : 52.1
},
{
"difficulty" : 2,
"score" : 74.3
},
{
"difficulty" : 5,
"score" : 53.1
}
]
}
]
我想对 return 两个最高 examScores.score
使用聚合
像这样:
[
{
name: "Max",
maxExams: [88.5, 62.1]
},
{
name: "Manu",
maxExams: [74.3, 53.1]
}
]
我尝试了聚合阶段 $project 和 $unwind 和 $sort
但是都没有解决我的问题
这里是:
mongos> db.s.aggregate([
{$unwind:"$examScores"},
{$sort:{"name":1,"examScores.score":-1}},
{$group:{ _id:"$name" ,Scores:{$push:"$examScores.score"} }},
{$project:{_id:0,name:"$_id",maxExam:{$slice:["$Scores",2]}}}
])
{ "name" : "Manu", "maxExam" : [ 74.3, 53.1 ] }
{ "name" : "Max", "maxExam" : [ 88.5, 62.1 ] }
mongos>
解释:
- 展开乐谱,以便稍后对它们进行排序。
- 按名称和分数从高到低排序
- 将分数分组到新数组 Scores
- 投影名称和 maxExam(从分数中切出前 2 个)
查询
- 您可以减少并仅保留最多 2 个分数
- 从
[-1,-1]
开始如果分数>=第一个成员添加左(旧的右将被删除),
else if score >= second member add right(old right will be removed), else 什么都不做
- 如果你想要超过 2-3 个
- 如果MongoDB5你
$setWindowFields
可以用
- else unwind group slice 2 解决方案
*这里你不需要 unwind/group/sort 等,因为只有 2.
aggregate(
[{"$project":
{"_id": 0,
"name": 1,
"maxExams":
{"$reduce":
{"input": "$examScores",
"initialValue": [-1, -1],
"in":
{"$switch":
{"branches":
[{"case":
{"$gte": ["$$this.score", {"$arrayElemAt": ["$$value", 0]}]},
"then":
{"$concatArrays":
[["$$this.score"], [{"$arrayElemAt": ["$$value", 0]}]]}},
{"case":
{"$gte": ["$$this.score", {"$arrayElemAt": ["$$value", 1]}]},
"then":
{"$concatArrays":
[[{"$arrayElemAt": ["$$value", 0]}], ["$$this.score"]]}}],
"default": "$$value"}}}}}}])
我有一个学生合集,如下所示: 如何找到每个学生最多两个考试成绩
[
{
"_id" : ObjectId("61868aa03b2fe72b58c891a5"),
"name" : "Max",
"examScores" : [
{
"difficulty" : 4,
"score" : 57.9
},
{
"difficulty" : 6,
"score" : 62.1
},
{
"difficulty" : 3,
"score" : 88.5
}
]
},
{
"_id" : ObjectId("61868aa03b2fe72b58c891a6"),
"name" : "Manu",
"examScores" : [
{
"difficulty" : 7,
"score" : 52.1
},
{
"difficulty" : 2,
"score" : 74.3
},
{
"difficulty" : 5,
"score" : 53.1
}
]
}
]
我想对 return 两个最高 examScores.score
使用聚合
像这样:
[
{
name: "Max",
maxExams: [88.5, 62.1]
},
{
name: "Manu",
maxExams: [74.3, 53.1]
}
]
我尝试了聚合阶段 $project 和 $unwind 和 $sort 但是都没有解决我的问题
这里是:
mongos> db.s.aggregate([
{$unwind:"$examScores"},
{$sort:{"name":1,"examScores.score":-1}},
{$group:{ _id:"$name" ,Scores:{$push:"$examScores.score"} }},
{$project:{_id:0,name:"$_id",maxExam:{$slice:["$Scores",2]}}}
])
{ "name" : "Manu", "maxExam" : [ 74.3, 53.1 ] }
{ "name" : "Max", "maxExam" : [ 88.5, 62.1 ] }
mongos>
解释:
- 展开乐谱,以便稍后对它们进行排序。
- 按名称和分数从高到低排序
- 将分数分组到新数组 Scores
- 投影名称和 maxExam(从分数中切出前 2 个)
查询
- 您可以减少并仅保留最多 2 个分数
- 从
[-1,-1]
开始如果分数>=第一个成员添加左(旧的右将被删除), else if score >= second member add right(old right will be removed), else 什么都不做 - 如果你想要超过 2-3 个
- 如果MongoDB5你
$setWindowFields
可以用 - else unwind group slice 2 解决方案
- 如果MongoDB5你
*这里你不需要 unwind/group/sort 等,因为只有 2.
aggregate(
[{"$project":
{"_id": 0,
"name": 1,
"maxExams":
{"$reduce":
{"input": "$examScores",
"initialValue": [-1, -1],
"in":
{"$switch":
{"branches":
[{"case":
{"$gte": ["$$this.score", {"$arrayElemAt": ["$$value", 0]}]},
"then":
{"$concatArrays":
[["$$this.score"], [{"$arrayElemAt": ["$$value", 0]}]]}},
{"case":
{"$gte": ["$$this.score", {"$arrayElemAt": ["$$value", 1]}]},
"then":
{"$concatArrays":
[[{"$arrayElemAt": ["$$value", 0]}], ["$$this.score"]]}}],
"default": "$$value"}}}}}}])