如何通过一个请求更新数组对象的多个字段?

Mad*_*h S 1 javascript mongoose mongodb node.js mongodb-query

{
   _id:xxxxstoreid
    store:{
        products:[
            {
                _id:xxxproductid,
                name:xxx,
                img:url,
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我无法预测更新请求,参数可能只有名称,也可能两者都有。

这是我的查询,它更新成功,但如果参数中不存在其他字段,它会删除它们。例如:

var params={_id:xxid,name:'xxx',img:'xxx'}
Run Code Online (Sandbox Code Playgroud)

或者

var params={_id:xxid,name:'xxx'}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果参数只有名称,它将删除 img 字段并更新。

User.update({'store.products._id':params._id},{$set:{"store.products":params}},callback);
Run Code Online (Sandbox Code Playgroud)

Nei*_*unn 5

$set您需要使用位置$运算符提供多个键来更新两个匹配的键。

我更喜欢现代 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);
Run Code Online (Sandbox Code Playgroud)

这将产生对 MongoDB 的调用(with mongoose.set('debug', true))打开,因此我们看到了请求:

Mongoose: users.update({ 'store.products._id': 'xxxproductid' }, { '$set': { 'store.products.$.name': 'xxx', 'store.products.$.img' : 'yyy' } }, {})

基本上,您获取输入params并提供_id作为“查询”的第一个参数:

  { 'store.products._id': params._id },
Run Code Online (Sandbox Code Playgroud)

其余部分从对象中获取“键”,通过Object.keys该“数组”我们可以使用该“数组”进行“过滤” Array.filter(),然后传递到Array.reduce将这些键转换为Object.

在内部,.reduce()我们调用Object.assign()它“合并”具有给定键的对象,以这种形式生成:

  Object.assign(acc,{ [`store.products.$.${curr}`]: params[curr] }),
Run Code Online (Sandbox Code Playgroud)

使用模板语法将“当前”(curr)“key”分配给新的键名称,再次使用允许对象文字中的变量名称的ES6 键分配语法。[]:

生成的“合并”对象被传回并分配给“根”对象,其中$set用于更新的密钥,因此“生成的”密钥现在是该对象的子对象。

我使用数组作为参数纯粹是为了调试目的,但这也允许在实际.update()使用“扩展”...运算符来分配参数时使用更清晰的语法:

User.update(...update,callback);
Run Code Online (Sandbox Code Playgroud)

简洁明了,还有一些您应该学习的用于对象和数组操作的 JavaScript 技术。主要是因为 MongoDB 查询 DSL 基本上是“对象”和“数组”。所以要学会操纵它们。