Това всъщност изисква "два" (или "три" с upsert ) оператора за актуализиране и е една от много добрите причини, поради които съществуват "Групови" операции.
db.collection.bulkWrite([
// Attempt to update the matched element
{ "updateOne": {
"filter": {
"name": "SweetTown",
"residents.name": "Bob"
},
"update": {
"$set": { "residents.$.reputation": 30 }
}
},
// $push the element where not matched
{ "updateOne": {
"filter": {
"name": "SweetTown",
"residents.name": { "$ne": "Bob" }
},
"update": {
"$push": {
"residents": { "name": "Bob", "reputation": 30 }
}
}
}}
])
Или ако наистина искате да включите "upsert"
за основния документ на "SweetTown"
тогава трябва да отделите това безпокойство в негов собствен тест:
db.collection.bulkWrite([
// Attempt to update the matched element
{ "updateOne": {
"filter": {
"name": "SweetTown",
"residents.name": "Bob"
},
"update": {
"$set": { "residents.$.reputation": 30 }
}
},
// $push the element where not matched
{ "updateOne": {
"filter": {
"name": "SweetTown",
"residents.name": { "$ne": "Bob" }
},
"update": {
"$push": {
"residents": { "name": "Bob", "reputation": 30 }
}
}
}},
// Only use $setOnInsert when actually an upsert
{ "updateOne": {
"filter": {
"name": "SweetTown"
},
"update": {
"$setOnInsert": {
"residents": [{ "name": "Bob", "reputation": 30 }]
}
},
"upsert": true
}}
])
Така че общата концепция е дасамо приложете $setOnInsert
действие при "upsert"
действително възниква. За да сме сигурни, че това се случва само в този случай, другите операции, които действително разглеждат елемента на масива, не са маркирани с "upsert"
опция. Тази част е нарочна.
Откъдето и да го погледнете, това е възможно само заедина от тези операции за действително извършване на някаква модификация в базата данни, тъй като или елементът е намерен или не, или дори документът не е намерен и е създаден нов.
В никакъв случай не е възможно да се извърши този вид операция в единичен израз за актуализиране. Въпреки това, тъй като „Груповите“ операции са наистина само един заявка седина отговор, тогава що се отнася до вашето приложение, то трябваше да говори със сървъра само веднъж за да накарате сървъра да опита всички тези три неща и да върне отговор.
За по-ранна употреба на директния Bulk API алтернативният синтаксис е:
var bulk = db.collection.initializeOrderedBulkOp();
// $set matched where existing
bulk.find({ "name": "SweetTown", "residents.name": "Bob" }).updateOne({
"$set": { "residents.$.reputation": 30 }
});
// $push where not existing
bulk.find({ "name": "SweetTown", "residents.name": { "$ne": "Bob" } }).updateOne({
"$push": { "residents": { "name": "Bob", "reputation": 30 } }
});
// Attempt to upsert only
bulk.find({ "name": "SweetTown" }).upsert().updateOne({
"$setOnInsert": {
"residents": [{ "name": "Bob", "reputation": 30 }]
}
})
bulk.execute();