I MongoDB er db.collection.findAndModify()
metoden ændrer og returnerer et enkelt dokument.
collection
del er navnet på den samling, som operationen skal udføres med.
Eksempel
Antag, at vi har en samling kaldet pets
der indeholder følgende dokumenter:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Vi kan bruge db.collection.findAndModify()
metode til at ændre et af disse dokumenter.
db.pets.findAndModify({
query: { type: "Dog" },
update: { type: "Cow" }
})
Resultat:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" }
Som standard returnerer den det originale dokument (ikke den ændrede version).
Bemærk, at kun én hund blev opdateret, selvom der er to hunde i samlingen.
Lad os tjekke samlingen.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Vi kan se, at det første dokument nu indeholder en ko i stedet for en hund. Vi kan dog også se, at dokumentets navnefelt er forsvundet.
Det er fordi, når du sender et dokument til update
argument, db.collection.findAndModify()
udfører en udskiftning.
Brug af en opdateringsoperatør
Hvis vi ville opdatere et felt, men lade resten af dokumentet være intakt, skulle vi inkludere det/de relevante opdateringsoperatørudtryk i vores dokument.
Med samlingen i dens nuværende tilstand, lad os udføre endnu en findAndModify()
operation mod det, men denne gang bruger vi $set
opdateringsoperatør for at indstille det felt, vi ønsker ændret.
db.pets.findAndModify({
query: { type: "Dog" },
update: { $set: { type: "Horse" } }
})
Resultat:
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
Denne gang blev den resterende hund opdateret.
Lad os tage et kig på samlingen.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Denne gang blev det relevante felt opdateret, og resten af dokumentet forblev intakt.
Returner det ændrede dokument
Som standard returneres det originale dokument, når du bruger db.collection.findAndModify()
.
Hvis du foretrækker at få det ændrede dokument returneret i stedet, skal du bruge new
parameter.
Som standard er dette new: false
, hvilket resulterer i, at det originale dokument returneres. Men ved at angive new: true
resulterer i, at det ændrede dokument returneres i stedet.
Lad os lave en anden ændring, men denne gang bruger vi new: true
.
db.pets.findAndModify({
query: { name: "Meow" },
update: { $set: { name: "Scratch" } },
new: true
})
Resultat:
{ "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Så vi omdøbte Meow
til Scratch
og outputtet afspejler vores ændringer.
Upserts
Du kan udføre upserts ved at angive upsert: true
.
En upsert er en mulighed, som du kan bruge til opdateringshandlinger. Hvis det angivne dokument ikke eksisterer, indsættes et nyt. Hvis det gør eksisterer, så opdateres det originale dokument (og intet dokument er indsat).
Eksempel med upsert: false
Her er et eksempel på forsøg på at opdatere et ikke-eksisterende dokument, når upsert: false
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true
})
Resultat:
null
Dokumentet eksisterede ikke i samlingen og derfor findAndModify()
returnerede null
. Selvom vi ikke specificerede upsert: false
, vi ved, at det var falsk, fordi det er standardværdien (dvs. det er den værdi, der bruges, når du ikke angiver en upsert-indstilling).
Hvis vi kigger igen i samlingen, kan vi se, at dokumentet ikke blev slettet.
db.pets.find()
Resultat:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Eksempel med upsert: true
Nu er den her igen, men denne gang angiver 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" }
Denne gang er et nyt dokument opsat, og vi ser det omdannede dokument som output (fordi vi har angivet new: true
).
Lad os tjekke 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, at det nye dokument faktisk blev ophævet.
ArrayFilters-parameteren
Når du arbejder med arrays, kan du bruge arrayFilters
parameter sammen med den positionelle $
operatør for at bestemme, hvilke array-elementer der skal opdateres. Dette giver dig mulighed for at opdatere et array-element baseret på dets værdi, selvom du ikke kender dets position.
Antag for eksempel, at vi har en samling kaldet players
med følgende dokumenter:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
Vi kunne køre følgende forespørgsel for kun at opdatere de array-elementer, der har en værdi højere end et bestemt beløb (i dette tilfælde 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 forventet opdaterer dette kun ét dokument, selvom to dokumenter matcher kriterierne.
Sådan ser dokumenterne ud 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 havde to array-elementer opdateret, fordi disse elementer matchede kriterierne.
Flere oplysninger
db.collection.findAndModify()
metode accepterer også andre parametre, såsom writeConcern
, collation
, bypassDocumentValidation
og mere.
Se MongoDB-dokumentationen for db.collections.findAndModify()
for mere information.