L'essentiel ici est l'agrégation $slice
pour obtenir le dernier élément du tableau,
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
]
}
}}
])
Je suis en fait "plus sûr" dans le $project
étape avec le $filter
mais c'est fondamentalement la même chose.
Tout d'abord, la requête sélectionne les documents, nous ne pouvons pas réellement dire à ce stade de faire correspondre "uniquement" le dernier élément du tableau, mais nous voulons filtrer les documents qui n'ont pas du tout la condition sur le tableau.
Le $redact
est la chose réelle qui regarde la "dernière" entrée du tableau et teste la valeur du champ. Nous pouvons noter uniquement le champ du tableau par $messages.capty
qui renvoie juste un tableau de ces éléments. Ici, nous avons alors $slice
ou même $arrayElemAt
si vous voulez obtenir la dernière valeur, étant l'index de -1
.
À ce stade, nous n'avons "filtré" que les "documents" qui ne correspondent pas à la condition. Le dernier $project
l'étape prend le dernier élément du tableau, vérifie qu'il correspond à la condition (ce qu'il devrait faire par les étapes précédentes), extrait la valeur de "body"
et transforme le contenu du tableau unique en une simple valeur.
Vous pouvez alternativement renoncer à la "attention" et simplement saisir le dernier élément du tableau depuis $redact
aurait dû faire son travail :
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 ]
}
}}
])
Le tout se décompose vraiment pour "correspondre au possible documents avec une requête" puis "comparez et extrayez le dernier élément avec $slice
ou $arrayElemAt
".
Les résultats sont :
{
"_id" : ObjectId("593921425ccc8150f35e7663"),
"user2" : 3,
"body" : "hiii 23"
}
{
"_id" : ObjectId("593921425ccc8150f35e7664"),
"user2" : 4,
"body" : "hiii 24"
}