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> 

解释:

  1. 展开乐谱,以便稍后对它们进行排序。
  2. 按名称和分数从高到低排序
  3. 将分数分组到新数组 Scores
  4. 投影名称和 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.

PlayMongo

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"}}}}}}])