Insert array where element does not exist else update it ( with multiple conditions )

拜拜、爱过 提交于 2020-01-05 02:37:46

问题


{
 _id:'1',
name:'apple',
option:[{
weight:'10',
size:'40'
price:'40',
},
{weight:'40',
 size:'40'
price:'200'}]
}

If weight or the size is different I want to upsert new object in the array, if both the size and the weight matched I want to update it. How can I do it?


回答1:


Similar to your previous question, you use .bulkWrite() but since the array element selection has "multiple conditions" this is where you use $elemMatch:

db.collection.bulkWrite([
  { "updateOne": {
    "filter": { 
      "_id": "1", 
      "option": { 
        "$elemMatch": { weight": "40", "size": "40" }
      }
    },
    "update": { 
      "$set": { "option.$.price": "300" }
    }
  }},
  { "updateOne": {
    "filter": {
      "_id": "1",
      "option": {
        "$not": {
          "$elemMatch": { weight": "40", "size": "40" }
        }
      }
    },
    "update": {
      "$push": { "option": { "weight": "40", "size": "40",  "price": "300" } }
    }
  }},
  { "updateOne": {
    "filter": { "_id": 1 },
    "update": {
      "$setOnInsert": {
        "option": [
           { "weight": "40", "size": "40",  "price": "300" }
         ]
      }
    },
    "upsert": true
  }}
])

So the operations are:

  1. Test that the array element matching conditions in $elemMatch is present and then $set the matched value.

  2. Test the array element is $not present in negation. You could alternately use $ne on each property, but negating the condition where both match is a bit cleaner.

    "$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
    

    At any rate you $push the new array element when one not matching the supplied criteria is found.

  3. Attempt an "upsert" only where the primary document _id is not found, and use $setOnInsert so that if the document is found this operation does nothing.

Same as before, only one of these will actually write anything despite the whole batch being sent to the server.




回答2:


You might be able to wire things together with a single, mongodb-only operation, you're probably better off by adding a 'version' field and using optimistic locking, like java+spring-data does it for you (google for @Version). That would allow for complex changes and validations of the full object before persistence.



来源:https://stackoverflow.com/questions/46806613/insert-array-where-element-does-not-exist-else-update-it-with-multiple-conditi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!