Il modo migliore per farlo è utilizzare il framework di aggregazione. Devi $group
i tuoi documenti per "utente" e restituisci l'ultimo documento per ogni utente usando il $last
accumulatore, ma affinché funzioni, è necessaria una fase di ordinamento preliminare utilizzando il $sort
operatore della pipeline di aggregazione. Per ordinare i tuoi documenti, devi considerare sia il campo "createdAt" che il campo "utente".
L'ultima fase della pipeline è il $match
fase in cui selezioni solo gli ultimi documenti in cui "isAbandoned" è uguale a true
.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
che restituisce qualcosa del genere:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
Per ottenere il risultato atteso, dobbiamo usare il $replaceRoot
operatore della pipeline a partire dalla versione 3.4 per promuovere il documento incorporato al livello superiore
{
$replaceRoot: { newRoot: "$last" }
}
Nella versione precedente, devi usare il $project
operazione di pipeline di aggregazione per rimodellare i nostri documenti. Quindi, se estendiamo la nostra pipeline con la fase seguente:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
produce l'output atteso:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}