Tengo una colección de estudiantes que se ve así: Cómo encontrar un máximo de dos puntajes de examen para cada estudiante
[ { "_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 } ] } ] Quiero usar la agregación para devolver los dos examScores.score más altos de esta manera:
[ { name: "Max", maxExams: [88.5, 62.1] }, { name: "Manu", maxExams: [74.3, 53.1] } ]Intenté la etapa de agregación $proyecto y $desenrollado y $clasificación, pero ninguno de ellos resuelve mi problema
Aquí está:
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>Explicado:
Consulta
[-1,-1] si el puntaje >= el primer miembro agrega a la izquierda (se eliminará el derecho anterior), de lo contrario, si el puntaje> = el segundo miembro agrega a la derecha (se eliminará el derecho anterior), de lo contrario no haga nada$setWindowFields*aquí no necesitas desconectar/agrupar/ordenar, etc. porque solo 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"}}}}}}])