MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Requête sur la dernière valeur du tableau

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"
}