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

mongoose opdatere array eller tilføje til arrayet

Hovedproblemet er, at findOneAndUpdate gør præcis, hvad navnet antyder. Den udfører en find ved at bruge det medfølgende filter, og hvis et match er fundet, anvender opdateringerne til det første matchende dokument.

Hvis samlingen kun indeholder dette dokument:

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

Den indledende find-del er i det væsentlige

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

Dette matcher intet, og da upsert er sat til sand, forsøger fineOneAndUpdate at oprette et helt nyt dokument. Selv hvis det var i stand til at oprette et array fra en uovertruffen positionsoperator, ville dokumentet, det ville forsøge at tilføje, være:

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

Dette er ikke korrekt og vil ikke kunne indsættes på grund af dublet _id værdi alligevel.

Hvis du bruger MongoDB 4.2, kan du bruge en aggregeringspipeline som det andet argument til findAndUpdate for at kontrollere arrayet for det element, du er interesseret i, og tilføje det, hvis det mangler.

En ikke særlig smuk metode er nedenfor. FindOneAndUpdate vil matche _id'et, og pipelinen vil:
- kontrollere, om et element i arrayet matcher den ønskede year_month
- Hvis ja, $reducere arrayet for at opdatere statusfeltet i det element
- Hvis ikke, tilføj et nyt element
- Tildel resultatet tilbage til 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}]
                  ]}
          ]}
     }}]
)


  1. mongo tæller rækker fra en række leverede data

  2. Effektiv POJO-kortlægning til/fra Java Mongo DBObject ved hjælp af Jackson

  3. Hvordan konverterer jeg en ejendom i MongoDB fra tekst til datotype?

  4. MongoDB $trunc