mongoose update array or add to the array

后端 未结 2 1447
刺人心
刺人心 2021-01-27 09:28

I\'ve been trying to get this running for a while now but I can\'t figure out what I\'m doing wrong.

I have two schemas like this

const paymentSchema = n         


        
2条回答
  •  隐瞒了意图╮
    2021-01-27 10:30

    The main problem is that findOneAndUpdate does exactly what its name implies. It executes a find using the provided filter, and if a match is found, applies the updates to the first matching document.

    If the collection contains only this document:

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

    The initial find part is essentially

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

    This matches nothing, and since upsert is set to true, fineOneAndUpdate attempts to create a brand new document. Even if it were able to create an array from an unmatched positional operator, the document it would be trying to add would be:

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

    This is not correct, and would fail to insert due to duplicate _id value anyway.

    If you are using MongoDB 4.2, you could use an aggregation pipeline as the second argument to findAndUpdate to check the array for the element you are interested in and add it if it is missing.

    One not very pretty method is below. The findOneAndUpdate will match the _id, and the pipeline will:
    - check if any element in the array matches the desired year_month
    - If so, $reduce the array to update the status field in that element
    - If not, append a new element
    - Assign the result back to 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}]
                      ]}
              ]}
         }}]
    )
    

提交回复
热议问题