To ve skutečnosti vyžaduje "dva" (nebo "tři" s upsert ) aktualizační prohlášení a je to jeden z velmi dobrých důvodů, proč existují "hromadné" operace.
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 }
}
}
}}
])
Nebo pokud jste skutečně chtěli zahrnout "upsert"
pro základní dokument "SweetTown"
pak musíte tuto obavu rozdělit do vlastního testu:
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
}}
])
Obecný koncept je tedy pouze použijte $setOnInsert
akce při "upsert"
skutečně dochází. Aby se zajistilo, že k tomu dojde pouze v tomto případě, ostatní operace, které se skutečně dívají na prvek pole, nejsou označeny "upsert"
volba. Ta část je záměrná.
Ať se na to podíváte z jakéhokoli úhlu, vždy je to možné jen jednou těchto operací skutečně provést jakoukoli úpravu v databázi, protože buď je prvek nalezen, nebo ne, nebo dokonce není nalezen dokument a je vytvořen nový.
V žádném případě není možné provést tento druh operace v jediném příkazu aktualizace. Protože však „hromadné“ operace jsou ve skutečnosti pouze jedna požádat o jednu odpověď, pak pokud jde o vaši aplikaci, pak stačilo jen mluvit se serverem jednou aby server vyzkoušel všechny tyto tři věci a vrátil odpověď.
Pro dřívější použití přímého Bulk API je alternativní syntaxe:
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();