问题
{
_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:
Test that the array element matching conditions in $elemMatch is present and then $set the matched value.
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.
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