Най-добрият начин да направите това е да използвате рамката за агрегиране. Трябва да $group
вашите документи по "потребител" и върнете последния документ за всеки потребител, като използвате $last
акумулаторен оператор, но за да работи това, имате нужда от предварителен етап на сортиране с помощта на $sort
оператор на тръбопровод за агрегация. За да сортирате документите си, трябва да вземете предвид както полето „createdAt“, така и полето „user“.
Последният етап в конвейера е $match
етап, в който избирате само онези последни документи, където „е изоставен“ е равно на true
.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
което връща нещо подобно:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
За да получим очаквания резултат, трябва да използваме $replaceRoot
оператор на тръбопровода, започвайки от версия 3.4, за да промотира вградения документ до най-високо ниво
{
$replaceRoot: { newRoot: "$last" }
}
В по-стара версия трябва да използвате $project
операция на тръбопровода за агрегиране, за да променим нашите документи. Така че, ако разширим нашия тръбопровод със следния етап:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
той произвежда очаквания изход:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}