MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Interrogazione sul valore dell'ultimo array

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