I MongoDB används db.collection.findAndModify()
metoden ändrar och returnerar ett enda dokument.
collection
del är namnet på samlingen med vilken operationen ska utföras.
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 kan använda db.collection.findAndModify()
metod för att ändra ett av dessa dokument.
db.pets.findAndModify({
query: { type: "Dog" },
update: { type: "Cow" }
})
Resultat:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" }
Som standard returnerar den originaldokumentet (inte den modifierade versionen).
Observera att endast en hund uppdaterades, även om det finns två hundar i samlingen.
Låt oss kolla in samlingen.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Vi kan se att det första dokumentet nu innehåller en ko istället för en hund. Men vi kan också se att dokumentets namnfält har försvunnit.
Det beror på att när du skickar ett dokument till update
argument, db.collection.findAndModify()
utför en ersättning.
Använda en uppdateringsoperatör
Om vi ville uppdatera ett fält, men lämna resten av dokumentet intakt, skulle vi behöva inkludera relevanta uppdateringsoperatoruttryck i vårt dokument.
Med samlingen i sitt nuvarande tillstånd, låt oss utföra en annan findAndModify()
operation mot det, men den här gången använder vi $set
uppdatera operatorn för att ställa in just det fält vi vill ändra.
db.pets.findAndModify({
query: { type: "Dog" },
update: { $set: { type: "Horse" } }
})
Resultat:
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
Den här gången uppdaterades den återstående hunden.
Låt oss ta en titt på samlingen.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Den här gången uppdaterades det relevanta fältet, och resten av dokumentet förblev intakt.
Returnera det ändrade dokumentet
Som standard returneras originaldokumentet när du använder db.collection.findAndModify()
.
Om du föredrar att få det ändrade dokumentet tillbaka istället, använd new
parameter.
Som standard är detta new: false
, vilket resulterar i att originaldokumentet returneras. Men anger new: true
resulterar i att det ändrade dokumentet returneras istället.
Låt oss göra en annan ändring, men den här gången använder vi new: true
.
db.pets.findAndModify({
query: { name: "Meow" },
update: { $set: { name: "Scratch" } },
new: true
})
Resultat:
{ "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Så vi döpte om Meow
till Scratch
och resultatet speglar våra förändringar.
Uppserts
Du kan utföra upserts genom att ange upsert: true
.
En upsert är ett alternativ som du kan använda vid uppdateringsoperationer. Om det angivna dokumentet inte finns infogas ett nytt. Om den gör det existerar, då uppdateras originaldokumentet (och inget dokument infogas).
Exempel med upsert: false
Här är ett exempel på hur man försöker uppdatera ett icke-existerande dokument när upsert: false
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true
})
Resultat:
null
Dokumentet fanns inte i samlingen och därför findAndModify()
returnerade null
. Även om vi inte angav upsert: false
, vi vet att det var falskt eftersom det är standardvärdet (dvs det är det värde som används när du inte anger ett upphävandealternativ).
Om vi tittar igen i samlingen kan vi se att dokumentet inte har rubbats.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Exempel med upsert: true
Nu är den här igen, men den här gången anger vi upsert: true
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true,
upsert: true
})
Resultat:
{ "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Den här gången läggs ett nytt dokument upp och vi ser det upphävda dokumentet som utdata (eftersom vi angav new: true
).
Låt oss kolla in samlingen igen.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" } { "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Så vi kan se att det nya dokumentet faktiskt var upphävt.
ArrayFilters-parametern
När du arbetar med arrayer kan du använda arrayFilters
parametern tillsammans med den positionella $
operatör för att bestämma vilka arrayelement som ska uppdateras. Detta gör att du kan uppdatera ett matriselement baserat på dess värde, även om du inte vet dess position.
Anta till exempel att vi har en samling som heter players
med följande dokument:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
Vi skulle kunna köra följande fråga för att bara uppdatera de arrayelement som har ett värde som är högre än ett visst belopp (i det här fallet 10).
db.players.findAndModify({
query: { scores: { $gte: 10 } },
update: { $set: { "scores.$[e]" : 10 } },
arrayFilters: [ { "e": { $gte: 10 } } ]
})
Resultat:
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
Som förväntat uppdaterar detta bara ett dokument, även om två dokument matchar kriterierna.
Så här ser dokumenten ut nu.
db.players.find()
Resultat:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 10, 10 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
Dokument 2 hade två arrayelement uppdaterade, eftersom dessa element matchade kriterierna.
Mer information
db.collection.findAndModify()
Metoden accepterar även andra parametrar, såsom writeConcern
, collation
, bypassDocumentValidation
och mer.
Se MongoDB-dokumentationen för db.collections.findAndModify()
för mer information.