sql >> Base de Datos >  >> NoSQL >> MongoDB

Consulta sobre el último valor de matriz

Lo principal aquí es la agregación $slice para obtener el último elemento de la matriz,

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

De hecho, estoy siendo "más seguro" en el $project etapa con el $filter pero todo es básicamente lo mismo.

Primero, la consulta selecciona los documentos, no podemos decir en este punto que "solo" coincida con el último elemento de la matriz, pero queremos filtrar los documentos que no tienen la condición en la matriz en absoluto.

El $redact es lo real que mira la "última" entrada de matriz y prueba el valor del campo. Podemos anotar solo el campo de la matriz mediante $messages.capty que devuelve solo una matriz de esos elementos. Aquí tenemos $slice o incluso $arrayElemAt si desea obtener el último valor, siendo el índice de -1 .

En este punto, solo "filtramos" los "documentos" que no cumplen la condición. El $project la etapa toma el último elemento de la matriz, verifica que coincida con la condición (que debería ser en las etapas anteriores), extrae el valor de "body" y convierte el contenido de la matriz única en el valor simple.

Alternativamente, puede renunciar al "cuidado" y simplemente tomar el último elemento de la matriz desde $redact debería haber hecho su trabajo:

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

Todo realmente se descompone para "coincidir con lo posible documentos con una consulta" y luego "comparar y extraer el último elemento con $slice o $arrayElemAt ".

Los resultados son:

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