Основното тук е агрегацията $slice
за да получите последния елемент от масива,
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
]
}
}}
])
Всъщност съм „по-голяма безопасност“ в $project
етап с $filter
но в общи линии всичко е същото.
Първо заявката избира документите, всъщност не можем да кажем на този етап да съответстваме „само“ на последния елемент от масива, но искаме да филтрираме документи, които изобщо нямат условието за масива.
$redact
е действителното нещо, което разглежда "последния" запис в масива и тества стойността на полето. Можем да обозначим само полето от масива чрез $messages.capty
който връща само масив от тези елементи. Тук след това $slice
или дори $arrayElemAt
ако искате да получите последната стойност, която е индексът на -1
.
На този етап ние само "филтрирахме" "документите", които не отговарят на условието. Последният $project
етапът взема последния елемент от масива, проверява дали отговаря на условието (което би трябвало на по-ранните етапи), извлича стойността на "body"
и превръща съдържанието на единичния масив само в обикновена стойност.
Можете алтернативно да се откажете от „внимателността“ и просто да вземете последния елемент от масива след $redact
трябваше да си свърши работата:
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 ]
}
}}
])
Цялото нещо наистина се разпада, за да „съвпадне с възможното документи със заявка" и след това "сравнете и извлечете последния елемент с $slice
или $arrayElemAt
".
Резултатите са:
{
"_id" : ObjectId("593921425ccc8150f35e7663"),
"user2" : 3,
"body" : "hiii 23"
}
{
"_id" : ObjectId("593921425ccc8150f35e7664"),
"user2" : 4,
"body" : "hiii 24"
}