Du måste ange flera nycklar till $set
med positionella $
operatör
för att uppdatera båda matchade nycklarna.
Jag föredrar det moderna ES6-sättet för objektmanipulation:
let params = { "_id" : "xxxproductid", "name" : "xxx", "img" : "yyy" };
let update = [
{ 'store.products._id': params._id },
{ "$set": Object.keys(params).filter(k => k != '_id')
.reduce((acc,curr) =>
Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
{ })
}
];
User.update(...update,callback);
Vilket skulle producera anropet till MongoDB som ( med mongoose.set('debug', true)
) aktiverat så att vi ser begäran:
Där du i princip tar dina indata params
och ange _id
som det första argumentet för "frågan" :
{ 'store.products._id': params._id },
Resten tar "nycklarna" från objektet via Object.keys
som gör en "array" som vi kan "filtrera" med Array.filter()
och skicka sedan till Array. minska
för att omvandla dessa nycklar till ett Objekt
.
Inuti .reduce()
vi kallar Object.assign()
som "slår samman" objekt med de givna nycklarna, genererade i denna form:
Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
Använd mallsyntaxen för att tilldela den "nuvarande" (curr) "nyckeln" till det nya nyckelnamnet, återigen med ES6-nyckeltilldelningssyntax []:
som tillåter variabelnamn i objektliteraler.
Det resulterande "merged"-objektet skickas tillbaka för att tilldelas till "root"-objektet där $set
används för nyckeln till uppdateringen, så de "genererade" nycklarna är nu barn till det.
Jag använder en array för argumenten enbart i felsökningssyfte, men då tillåter det också renare syntax på den faktiska .update()
med "spridningen" ...
operatorn för att tilldela argumenten:
User.update(...update,callback);
Rent och enkelt, och några JavaScript-tekniker som du bör lära dig för objekt- och arraymanipulation. Mestadels eftersom MongoDB-frågan DSL i princip är "Objekt" och "Arrayer". Så lär dig att manipulera dem.