Najlepszym sposobem na to jest użycie struktury agregacji. Musisz $group
twoje dokumenty przez "użytkownika" i zwróć ostatni dokument dla każdego użytkownika za pomocą $last
operatora akumulatora, ale aby to zadziałało, potrzebujesz wstępnego etapu sortowania za pomocą $sort
operator potoku agregacji. Aby posortować dokumenty, musisz wziąć pod uwagę zarówno pole „createdAt”, jak i pole „użytkownik”.
Ostatnim etapem potoku jest $match
etap, na którym wybierasz tylko te ostatnie dokumenty, w których „jest porzucone” równa się true
.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
co zwraca coś takiego:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
Aby uzyskać oczekiwany wynik, musimy użyć $replaceRoot
operator potoku, począwszy od wersji 3.4, aby promować osadzony dokument na najwyższy poziom
{
$replaceRoot: { newRoot: "$last" }
}
W starszej wersji musisz użyć $project
operacja potoku agregacji w celu przekształcenia naszych dokumentów. Więc jeśli przedłużymy nasz potok o następujący etap:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
daje oczekiwany wynik:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}