Het belangrijkste hier is de aggregatie $slice
om het laatste element uit de array te halen,
db.chat.aggregate([
{ "$match": { "user1": 1, "messages.capty": "B" } },
{ "$redact": {
"$cond": {
"if": {
"$eq": [ { "$slice": [ "$messages.capty", -1 ] }, ["B"] ]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"user2": 1,
"body": {
"$arrayElemAt": [
{ "$map": {
"input": {
"$filter": {
"input": { "$slice": [ "$messages",-1 ] },
"as": "m",
"cond": { "$eq": [ "$$m.capty", "B" ] }
}
},
"as": "m",
"in": "$$m.body"
}},
0
]
}
}}
])
Ik ben eigenlijk "extra veilig" in het $project
stage met de $filter
maar het is eigenlijk allemaal hetzelfde.
Eerst selecteert de query de documenten, we kunnen op dit moment niet zeggen dat ze "alleen" overeenkomen met het laatste element van de array, maar we willen documenten filteren die de voorwaarde helemaal niet in de array hebben.
De $redact
is het eigenlijke ding dat naar het "laatste" array-item kijkt en de waarde van het veld test. We kunnen alleen het veld uit de array noteren met $messages.capty
die slechts een array van die items retourneert. Hier hebben we dan $slice
of zelfs $arrayElemAt
als je de laatste waarde wilt krijgen, zijnde de index van -1
.
Op dit punt hebben we alleen de "documenten" "gefilterd" die niet overeenkomen met de voorwaarde. De laatste $project
stage neemt het laatste element van de array, controleert of het overeenkomt met de voorwaarde (wat het zou moeten doen door de eerdere fasen), extraheert de waarde van "body"
en verandert de enkele array-inhoud in alleen de gewone waarde.
Je kunt ook afzien van de "voorzichtigheid" en gewoon het laatste array-element pakken sinds $redact
had zijn werk moeten doen:
db.chat.aggregate([
{ "$match": { "user1": 1, "messages.capty": "B" } },
{ "$redact": {
"$cond": {
"if": {
"$eq": [ { "$arrayElemAt": [ "$messages.capty", -1 ] }, "B" ]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"user2": 1,
"body": {
"$arrayElemAt": [ "$messages.body", -1 ]
}
}}
])
Het hele ding valt echt uiteen om "te matchen met de mogelijke documenten met een query" en vervolgens "vergelijk en extraheer het laatste element met $slice
of $arrayElemAt
".
Resultaten zijn:
{
"_id" : ObjectId("593921425ccc8150f35e7663"),
"user2" : 3,
"body" : "hiii 23"
}
{
"_id" : ObjectId("593921425ccc8150f35e7664"),
"user2" : 4,
"body" : "hiii 24"
}