Många uppdateringsoperationer i MongoDB har potential att bli upprörda. En upsert är en kombination av en insert och en uppdatering.
Det fungerar så här:Du utför en uppdateringsoperation baserat på filterkriterier, och om det finns några matchningar uppdateras bara de matchade dokumenten, men om det inte finns några matchningar infogas ett nytt dokument.
Exempel
Anta att vi har en samling som heter pets
som innehåller följande dokument:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Vi skulle kunna utföra följande uppdateringsoperation som ställer in upsert
parameter till true
:
db.pets.updateOne(
{ name: "Wag" },
{ $set: { type: "Cow" } },
{ upsert: true }
)
Resultat:
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
I det här fallet fanns det ett matchande dokument (dvs. det finns ett dokument med name: "Wag"
) och därför uppdaterades det matchande dokumentet. Inget infogades.
Vi kan verifiera detta enligt följande:
db.pets.find()
Resultat:
{ "_id" : 1, "name" : "Wag", "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Det första dokumentet har nu en type
av Cow
.
Låt oss köra ytterligare en uppdateringsoperation, igen med upsert: true
. Men den här gången kommer det inte att finnas något matchande dokument att uppdatera.
db.pets.updateOne(
{ name: "Bubbles" },
{ $set: { type: "Fish" } },
{ upsert: true }
)
Resultat:
{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0, "upsertedId" : ObjectId("5fe1b4c8d9914101694100b7") }
I det här exemplet försöker vi hitta ett dokument som har name: "Bubbles"
men det finns ingen att hitta.
Den här gången kan vi se att matchedCount
är 0
och modifiedCount
är också 0
. Det betyder att inga av de befintliga dokumenten uppdaterades.
Vi kan också se att ett upsertedId
returnerades, vilket betyder att ett dokument har rubbats.
Låt oss ta en ny titt på samlingen av dokument:
db.pets.find()
Resultat:
{ "_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" }
Vi kan se att ett nytt dokument har infogats/upphävts och det har samma ID som anges ovan.
Upphävningen inträffade eftersom det den här gången inte fanns några matchande dokument att uppdatera (och så ett nytt infogades/uppsattes istället).
Om vi inte hade ställt in upsert: true
, det dokumentet skulle inte ha infogats.
Upsert på massuppdateringar
När du utför en massuppdatering, om du vill ange upsert: true
, måste du använda den med Bulk.find.upsert()
.
Detta kan användas med följande skrivoperationer:
Bulk.find.replaceOne()
Bulk.find.updateOne()
Bulk.find.update()
Syntaxen ser ut så här:
Bulk.find(<query>).upsert().update(<update>);
Bulk.find(<query>).upsert().updateOne(<update>);
Bulk.find(<query>).upsert().replaceOne(<replacement>);
Exempel:
var bulk = db.pets.initializeUnorderedBulkOp();
bulk.find( { name: "Bruce" } ).upsert().replaceOne(
{
name: "Bruce",
type: "Bat",
}
);
bulk.execute();
Resultat:
BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 0, "nUpserted" : 1, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ { "index" : 0, "_id" : ObjectId("5fe1c179d9914101694100dd") } ] })
Vi kan se att ett dokument har rubbats. Vi kan också se _id
som skapades för det dokumentet.
Nu när vi tittar på dokumenten i vår samling kan vi se det nya dokumentet som har rubbats:
db.pets.find()
Resultat:
{ "_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" }