Você precisa fornecer as várias chaves para
$set
com o $
posicional operador
para atualizar ambas as chaves correspondentes. Eu prefiro a maneira moderna de manipulação 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);
O que produziria a chamada para o MongoDB como ( with
mongoose.set('debug', true)
) ativado para que possamos ver a solicitação:Onde basicamente você pega sua entrada
params
e forneça o _id
como o primeiro argumento para a "consulta": { 'store.products._id': params._id },
O resto pega as "chaves" do objeto via
Object.keys
que faz um "array" que podemos "filtrar" com Array.filter()
e depois passe para Array. reduzir
para transformar essas chaves em um Object
. Dentro do
.reduce()
chamamos Object.assign()
que "mescla" objetos com as chaves fornecidas, geradas desta forma: Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
Usando a sintaxe do modelo para atribuir a "chave" atual (curr) ao novo nome da chave, novamente usando o Sintaxe de atribuição de chave ES6
[]:
que permite nomes de variáveis em literais de objeto. O objeto "mesclado" resultante é passado de volta para ser atribuído ao objeto "raiz" onde
$set
é usado para a chave da atualização, então as chaves "geradas" agora são filhas disso. Eu uso uma matriz para os argumentos puramente para fins de depuração, mas isso também permite uma sintaxe mais limpa no
.update()
real. usando o "spread" ...
operador para atribuir os argumentos:User.update(...update,callback);
Limpo e simples, e algumas técnicas de JavaScript que você deve aprender para manipulação de objetos e arrays. Principalmente porque a DSL de consulta do MongoDB é basicamente "Objetos" e "Matrizes". Então aprenda a manipulá-los.