Devi fornire più chiavi a $set
con il posizionale $
operatore
per aggiornare entrambe le chiavi abbinate.
Preferisco il moderno modo ES6 di manipolazione degli oggetti:
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);
Che produrrebbe la chiamata a MongoDB come ( con mongoose.set('debug', true)
) attivato in modo da visualizzare la richiesta:
Dove fondamentalmente prendi i tuoi params
di input e fornisci il _id
come primo argomento per la "query" :
{ 'store.products._id': params._id },
Il resto prende le "chiavi" dall'oggetto tramite Object.keys
che crea un "array" che possiamo "filtrare" con Array.filter()
e quindi passare a Array.reduce
per trasformare quelle chiavi in un Object
.
All'interno di .reduce()
chiamiamo Object.assign()
che "fonde" gli oggetti con le chiavi date, generate in questa forma:
Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
Usando la sintassi del modello per assegnare la "chiave" "corrente" (curr) al nuovo nome della chiave, sempre usando Sintassi assegnazione tasti ES6 []:
che consente nomi di variabili in valori letterali oggetto.
L'oggetto "unito" risultante viene restituito per essere assegnato all'oggetto "root" dove $set
viene utilizzato per la chiave dell'aggiornamento, quindi le chiavi "generate" ora sono figli di quella.
Uso un array per gli argomenti esclusivamente a scopo di debug, ma ciò consente anche una sintassi più pulita sull'attuale .update()
usando il ...
di "spread". operatore per assegnare gli argomenti:
User.update(...update,callback);
Pulito e semplice e alcune tecniche JavaScript che dovresti imparare per la manipolazione di oggetti e array. Principalmente poiché la query MongoDB DSL è fondamentalmente "Oggetti" e "Array". Quindi impara a manipolarli.