Много операции за актуализиране в MongoDB имат потенциал да бъдат неудобни. Upsert е комбинация от вмъкване и актуализация.
Работи по следния начин:Вие извършвате операция за актуализиране въз основа на критерии за филтриране и ако има съвпадения, само съвпадащите документи се актуализират, но ако няма съвпадения, тогава се вмъква нов документ.
Пример
Да предположим, че имаме колекция, наречена pets който съдържа следните документи:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" }
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
{ "_id" : 3, "name" : "Meow", "type" : "Cat" }
Бихме могли да извършим следната операция за актуализиране, която задава upsert параметър на true :
db.pets.updateOne(
{ name: "Wag" },
{ $set: { type: "Cow" } },
{ upsert: true }
) Резултат:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
В този случай имаше съвпадащ документ (т.е. има документ с name: "Wag" ) и следователно съответстващият документ беше актуализиран. Нищо не беше въведено.
Можем да проверим това, както следва:
db.pets.find() Резултат:
{ "_id" : 1, "name" : "Wag", "type" : "Cow" }
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
{ "_id" : 3, "name" : "Meow", "type" : "Cat" }
Първият документ вече има type на Cow .
Нека стартираме друга операция за актуализиране, отново използвайки upsert: true . Но този път няма да има съответстващ документ за актуализиране.
db.pets.updateOne(
{ name: "Bubbles" },
{ $set: { type: "Fish" } },
{ upsert: true }
) Резултат:
{
"acknowledged" : true,
"matchedCount" : 0,
"modifiedCount" : 0,
"upsertedId" : ObjectId("5fe1b4c8d9914101694100b7")
}
В този пример се опитваме да намерим документ, който има name: "Bubbles" но не може да бъде намерен.
Този път можем да видим, че matchedCount е 0 и modifiedCount също е 0 . Това означава, че нито един от съществуващите документи не е актуализиран.
Можем също да видим, че upsertedId е върнат, което означава, че документът е бил въведен.
Нека да разгледаме отново колекцията от документи:
db.pets.find() Резултат:
{ "_id" : 1, "name" : "Wag", "type" : "Cow" }
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
{ "_id" : 3, "name" : "Meow", "type" : "Cat" }
{ "_id" : ObjectId("5fe1b4c8d9914101694100b7"), "name" : "Bubbles", "type" : "Fish" } Можем да видим, че нов документ е вмъкнат/поставен и той има същия идентификатор, както е посочено по-горе.
Превъртането се случи, защото този път нямаше съответстващи документи за актуализиране (и затова вместо това беше вмъкнат/внесен нов).
Ако не бяхме задали upsert: true , този документ нямаше да бъде вмъкнат.
Upsert при групови актуализации
Когато извършвате групова актуализация, ако искате да посочите upsert: true , трябва да го използвате с Bulk.find.upsert() .
Това може да се използва със следните операции за запис:
Bulk.find.replaceOne()Bulk.find.updateOne()Bulk.find.update()
Синтаксисът е така:
Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>); Пример:
var bulk = db.pets.initializeUnorderedBulkOp();
bulk.find( { name: "Bruce" } ).upsert().replaceOne(
{
name: "Bruce",
type: "Bat",
}
);
bulk.execute(); Резултат:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 1,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [
{
"index" : 0,
"_id" : ObjectId("5fe1c179d9914101694100dd")
}
]
})
Виждаме, че един документ е бил поставен. Можем също да видим _id който е генериран за този документ.
Сега, когато преглеждаме документите в нашата колекция, можем да видим новия документ, който беше въведен:
db.pets.find() Резултат:
{ "_id" : 1, "name" : "Wag", "type" : "Cow" }
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
{ "_id" : 3, "name" : "Meow", "type" : "Cat" }
{ "_id" : ObjectId("5fe1b4c8d9914101694100b7"), "name" : "Bubbles", "type" : "Fish" }
{ "_id" : ObjectId("5fe1c179d9914101694100dd"), "name" : "Bruce", "type" : "Bat" }