Много операции за актуализиране в 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" }