Så som du noterar är standarden i mongoose att när du "bäddar in" data i en array som denna får du ett _id
värde för varje matrispost som en del av dess egna underdokumentegenskaper. Du kan faktiskt använda detta värde för att bestämma indexet för objektet som du tänker uppdatera. MongoDB-sättet att göra detta är den positionella $
operatorvariabel, som håller den "matchade" positionen i arrayen:
Folder.findOneAndUpdate(
{ "_id": folderId, "permissions._id": permission._id },
{
"$set": {
"permissions.$": permission
}
},
function(err,doc) {
}
);
Den där .findOneAndUpdate()
metod returnerar det modifierade dokumentet eller annars kan du bara använda .update()
som en metod om du inte behöver returnera dokumentet. Huvuddelarna är att "matcha" elementet i arrayen för att uppdatera och "identifiera" som matchar den positionella $
som nämnts tidigare.
Sedan använder du naturligtvis $set
operatör så att endast elementen du anger skickas faktiskt "over the wire" till servern. Du kan ta detta vidare med "dot notation" och bara ange de element du faktiskt vill uppdatera. Som i:
Folder.findOneAndUpdate(
{ "_id": folderId, "permissions._id": permission._id },
{
"$set": {
"permissions.$.role": permission.role
}
},
function(err,doc) {
}
);
Så det här är flexibiliteten som MongoDB ger, där du kan vara väldigt "riktad" i hur du faktiskt uppdaterar ett dokument.
Vad detta dock gör är att "förbigå" all logik du kan ha inbyggt i ditt "mongoose"-schema, såsom "validering" eller andra "pre-save krokar". Det beror på att det "optimala" sättet är en MongoDB "funktion" och hur den är designad. Mongoose själv försöker vara en "bekvämlighet" omslag över denna logik. Men om du är beredd att ta lite kontroll själv, då kan uppdateringarna göras på det mest optimala sättet.
Så där det är möjligt för att göra det, håll din data "inbäddad" och använd inte refererade modeller. Det tillåter atomuppdatering av både "förälder" och "barn" objekt i enkla uppdateringar där du inte behöver oroa dig för samtidighet. Det är förmodligen en av anledningarna till att du borde ha valt MongoDB i första hand.