Mnoho aktualizačních operací v MongoDB má potenciál být naštvané. Upsert je kombinací vložky a aktualizace.
Funguje to takto:Provedete operaci aktualizace na základě kritérií filtru, a pokud existují nějaké shody, aktualizují se pouze odpovídající dokumenty, ale pokud nejsou žádné shody, vloží se nový dokument.
Příklad
Předpokládejme, že máme sbírku nazvanou pets
který obsahuje následující dokumenty:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Mohli bychom provést následující aktualizaci, která nastaví upsert
parametr na true
:
db.pets.updateOne(
{ name: "Wag" },
{ $set: { type: "Cow" } },
{ upsert: true }
)
Výsledek:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
V tomto případě existoval odpovídající dokument (tj. existuje dokument s name: "Wag"
), a proto byl odpovídající dokument aktualizován. Nic nebylo vloženo.
Můžeme to ověřit následovně:
db.pets.find()
Výsledek:
{ "_id" : 1, "name" : "Wag", "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
První dokument má nyní type
z Cow
.
Spusťte další operaci aktualizace, opět pomocí upsert: true
. Tentokrát však nebude k dispozici žádný odpovídající dokument k aktualizaci.
db.pets.updateOne(
{ name: "Bubbles" },
{ $set: { type: "Fish" } },
{ upsert: true }
)
Výsledek:
{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0, "upsertedId" : ObjectId("5fe1b4c8d9914101694100b7") }
V tomto příkladu se snažíme najít dokument, který má name: "Bubbles"
ale žádný se nenašel.
Tentokrát vidíme, že matchedCount
je 0
a modifiedCount
je také 0
. To znamená, že žádný z existujících dokumentů nebyl aktualizován.
Můžeme také vidět, že upsertedId
byl vrácen, což znamená, že dokument byl přemístěn.
Podívejme se znovu na sbírku dokumentů:
db.pets.find()
Výsledek:
{ "_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" }
Vidíme, že byl vložen/upsertován nový dokument a má stejné ID, jak je uvedeno výše.
Upsert nastal, protože tentokrát nebyly žádné odpovídající dokumenty k aktualizaci (a tak byl místo toho vložen/upsertován nový).
Pokud bychom nenastavili upsert: true
, tento dokument by nebyl vložen.
Upsert na hromadné aktualizace
Při hromadné aktualizaci, pokud chcete zadat upsert: true
, musíte jej použít s Bulk.find.upsert()
.
To lze použít s následujícími operacemi zápisu:
Bulk.find.replaceOne()
Bulk.find.updateOne()
Bulk.find.update()
Syntaxe vypadá takto:
Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>);
Příklad:
var bulk = db.pets.initializeUnorderedBulkOp();
bulk.find( { name: "Bruce" } ).upsert().replaceOne(
{
name: "Bruce",
type: "Bat",
}
);
bulk.execute();
Výsledek:
BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 0, "nUpserted" : 1, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ { "index" : 0, "_id" : ObjectId("5fe1c179d9914101694100dd") } ] })
Vidíme, že jeden dokument byl převrácen. Můžeme také vidět _id
který byl pro daný dokument vygenerován.
Nyní, když si prohlížíme dokumenty v naší sbírce, můžeme vidět nový dokument, který byl přepsán:
db.pets.find()
Výsledek:
{ "_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" }