La meilleure façon de le faire est d'utiliser le cadre d'agrégation. Vous devez $group
vos documents par "utilisateur" et retournez le dernier document pour chaque utilisateur en utilisant le $last
opérateur d'accumulateur mais pour que cela fonctionne, vous avez besoin d'une étape de tri préalable en utilisant le $sort
opérateur de pipeline d'agrégation. Pour trier vos documents, vous devez tenir compte à la fois du champ "createdAt" et du champ "user".
La dernière étape du pipeline est le $match
étape où vous ne sélectionnez que les derniers documents où "isAbandoned" est égal à true
.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
qui renvoie quelque chose comme ceci :
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
Pour obtenir le résultat attendu, nous devons utiliser le $replaceRoot
opérateur de pipeline à partir de la version 3.4 pour promouvoir le document intégré au plus haut niveau
{
$replaceRoot: { newRoot: "$last" }
}
Dans l'ancienne version, vous devez utiliser le $project
opération de pipeline d'agrégation pour remodeler nos documents. Donc, si nous étendons notre pipeline avec l'étape suivante :
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
il produit la sortie attendue :
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}