Det bästa sättet att göra detta är att använda aggregeringsramverket. Du måste $group
dina dokument efter "användare" och returnera det sista dokumentet för varje användare med $last
ackumulatoroperatör men för att detta ska fungera behöver du ett preliminärt sorteringssteg med $sort
aggregeringsrörledningsoperatör. För att sortera dina dokument måste du ta hänsyn till både "createdAt"-fältet och "user"-fältet.
Det sista steget i pipelinen är $match
steg där du bara väljer de sista dokumenten där "isAbandoned" är lika med true
.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
som returnerar ungefär så här:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
För att få det förväntade resultatet måste vi använda $replaceRoot
pipeline-operatör från och med version 3.4 för att främja det inbäddade dokumentet till toppnivå
{
$replaceRoot: { newRoot: "$last" }
}
I äldre version måste du använda $project
aggregeringspipelinedrift för att omforma våra dokument. Så om vi utökar vår pipeline med följande steg:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
den producerar den förväntade utdata:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}