La cosa principale qui è l'aggregazione $slice
per ottenere l'ultimo elemento dall'array,
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
]
}
}}
])
In realtà sono "extra sicuro" nel $project
stage con $filter
ma praticamente è tutto lo stesso.
Per prima cosa la query seleziona i documenti, a questo punto non possiamo effettivamente dire di corrispondere "solo" all'ultimo elemento dell'array, ma vogliamo filtrare i documenti che non hanno affatto la condizione sull'array.
Il $redact
è l'oggetto effettivo che esamina l'"ultima" voce dell'array e verifica il valore del campo. Possiamo annotare solo il campo dell'array con $messages.capty
che restituisce solo un array di quegli elementi. Ecco quindi $slice
o anche $arrayElemAt
se vuoi ottenere l'ultimo valore, essendo l'indice di -1
.
A questo punto abbiamo solo "filtrato" i "documenti" che non soddisfano la condizione. L'ultimo $project
stage prende l'ultimo elemento dell'array, controlla che corrisponda alla condizione (che dovrebbe essere per gli stadi precedenti), estrae il valore di "body"
e trasforma il contenuto del singolo array nel valore normale.
In alternativa puoi rinunciare alla "attenzione" e semplicemente afferrare l'ultimo elemento dell'array da $redact
avrebbe dovuto fare il suo lavoro:
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 ]
}
}}
])
Il tutto si scompone davvero per "corrispondere al possibile". documenti con una query" e poi "confronta ed estrai l'ultimo elemento con $slice
o $arrayElemAt
".
I risultati sono:
{
"_id" : ObjectId("593921425ccc8150f35e7663"),
"user2" : 3,
"body" : "hiii 23"
}
{
"_id" : ObjectId("593921425ccc8150f35e7664"),
"user2" : 4,
"body" : "hiii 24"
}