MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Abfrage nach letztem Array-Wert

Die Hauptsache hier ist die Aggregation $slice um das letzte Element aus dem Array zu erhalten,

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
     ]
   }
 }}
])

Ich bin im $project Schritt mit dem $filter aber es ist im Grunde alles dasselbe.

Zuerst wählt die Abfrage die Dokumente aus, wir können an dieser Stelle nicht wirklich sagen, dass „nur“ das letzte Element des Arrays passt, aber wir wollen Dokumente filtern, die die Bedingung überhaupt nicht im Array haben.

Der $redact ist die eigentliche Sache, die den "letzten" Array-Eintrag betrachtet und den Wert des Felds testet. Wir können nur das Feld aus dem Array mit $messages.capty notieren die nur ein Array dieser Elemente zurückgibt. Hier haben wir dann $slice oder sogar $arrayElemAt Wenn Sie den letzten Wert erhalten möchten, ist dies der Index von -1 .

An dieser Stelle haben wir nur die "Dokumente" "gefiltert", die nicht der Bedingung entsprechen. Der letzte $project stage nimmt das letzte Element des Arrays, prüft, ob es der Bedingung entspricht (was es von den früheren Stadien erwarten sollte), extrahiert den Wert von "body" und wandelt den einzelnen Array-Inhalt in den einfachen Wert um.

Alternativ können Sie auch auf die „Sorgfalt“ verzichten und einfach das letzte Array-Element seit $redact greifen hätte seinen Job machen sollen:

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 ]
   }
 }}
])

Das Ganze bricht wirklich zusammen, um "das Mögliche zu erreichen Dokumente mit einer Abfrage" und dann "das letzte Element vergleichen und extrahieren mit $slice oder $arrayElemAt ".

Ergebnisse sind:

{
        "_id" : ObjectId("593921425ccc8150f35e7663"),
        "user2" : 3,
        "body" : "hiii 23"
}
{
        "_id" : ObjectId("593921425ccc8150f35e7664"),
        "user2" : 4,
        "body" : "hiii 24"
}