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

mongoose actualizar matriz o agregar a la matriz

El principal problema es que findOneAndUpdate hace exactamente lo que su nombre implica. Ejecuta un find utilizando el filtro proporcionado y, si se encuentra una coincidencia, aplica las actualizaciones al primer documento coincidente.

Si la colección contiene solo este documento:

[
    {
        "_id": "5e90ae0e0ed9974174e92826",
        "payments": [
            {
                "year_month": "2020_02",
                "status": false
            }
        ]
    }
]

La parte de búsqueda inicial es esencialmente

.find({
        _id: '5e90ae0e0ed9974174e92826',
        payments: { $elemMatch: { year_month: '2020_03' }}
})

Esto no coincide con nada, y dado que upsert se establece en verdadero, fineOneAndUpdate intenta crear un documento nuevo. Incluso si pudiera crear una matriz a partir de un operador posicional no coincidente, el documento que intentaría agregar sería:

 {
        "_id": "5e90ae0e0ed9974174e92826",
        "payments": [
            {
                "year_month": "2020_03",
                "status": false
            }
        ]
}

Esto no es correcto y no se podría insertar debido a un _id duplicado valor de todos modos.

Si usa MongoDB 4.2, podría usar una canalización de agregación como segundo argumento para findAndUpdate para buscar en la matriz el elemento que le interesa y agregarlo si falta.

Un método no muy bonito está debajo. FindOneAndUpdate coincidirá con el _id, y la canalización:
- comprobará si algún elemento de la matriz coincide con el año_mes deseado
- Si es así, $reduzca la matriz para actualizar el campo de estado en ese elemento
- Si no, agregue un nuevo elemento
- Asigne el resultado de nuevo a payments

.findOneAndUpdate(
    { "_id": "5e90ae0e0ed9974174e92826" },
    [{$set: {
         payments: {$cond:[
                 {$gt:[
                       {$size:
                             {$filter:{
                                  input:"$payments", 
                                  cond:{$eq:["$$this.year_month","2020_03"]}
                       }}},
                       1
                  ]},
                  {$reduce:{
                        input:"$payments",
                        initialValue:[],
                        in:{$concatArrays:[
                                  "$$value",
                                  [{$cond:[
                                       {$eq:["$$this.j",3]},
                                       {$mergeObjects:["$$this",{status:true}]},
                                       "$$this"
                                  ]}]
                        ]}
                  }},
                  {$concatArrays:[
                       "$payments",
                       [{year_month:"2020_03", status:true}]
                  ]}
          ]}
     }}]
)