Debe proporcionar varias claves para $set
con el posicional $
operador
para actualizar ambas claves coincidentes.
Prefiero la forma moderna de manipulación de objetos ES6:
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);
Lo que produciría la llamada a MongoDB como (con mongoose.set('debug', true)
) activado para que veamos la solicitud:
Donde básicamente tomas tu entrada params
y proporcione el _id
como primer argumento para la "consulta":
{ 'store.products._id': params._id },
El resto toma las "claves" del objeto mediante Object.keys
que crea una "matriz" que podemos "filtrar" con Array.filter()
y luego pase a Array.reduce
para transformar esas claves en un Object
.
Dentro de .reduce()
llamamos a Object.assign()
que "fusiona" objetos con las claves dadas, generadas de esta forma:
Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
Usando la sintaxis de la plantilla para asignar la "clave" "actual" (curr) en el nuevo nombre de la clave, nuevamente usando Sintaxis de asignación de teclas ES6 []:
que permite nombres de variables en objetos literales.
El objeto "combinado" resultante se devuelve para asignarlo al objeto "raíz" donde $set
se usa para la clave de la actualización, por lo que las claves "generadas" ahora son secundarias.
Utilizo una matriz para los argumentos únicamente con fines de depuración, pero eso también permite una sintaxis más limpia en el .update()
real. usando el "spread" ...
operador para asignar los argumentos:
User.update(...update,callback);
Limpio y simple, y algunas técnicas de JavaScript que debe aprender para la manipulación de objetos y matrices. Sobre todo porque la consulta de MongoDB DSL es básicamente "Objetos" y "Matrices". Así que aprende a manipularlos.