Node.js - Mongoose - 使用req.body中的所有值更新嵌套数组

Jac*_*cob 3 javascript mongoose mongodb node.js express

我有一个看起来像这样的对象.

{
  _id: '577fe7a842c9b447',
  name: 'Jacob\'s Bronze Badges',
  competitors: [
    {
      _id: '577fe7a842c9bd6d',
      name: 'Peter\'s Silver Badges',
      sites: [
        {
          _id: '577fe7a842c9bd6d',
          name: 'Facebook',
          url: 'fb.com/peter'
        },
        {
          _id: '577fe7a842c9bd6d'
          name: 'Google',
          url: 'google.com/peter'
        }
      ]
    },
    {
      _id: '599fe7a842c9bd6d',
      name: 'Paul\'s Gold Badges',
      sites: [
        {
          '_id': '577fe7a842c9bd6d',
          name: 'Facebook',
          url: 'fb.com/paul'
        },
        {
          _id: '577fe7a842c9bd6d',
          name: 'Google',
          url: 'google.com/paul'
        }
      ]
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我的目标是引用competitors数组并使用所有值更新内部的项目req.body.我基于这个代码关闭的这个答案,以及该另一个.

Location.update(
  { 'competitors._id': req.params.competitorId, },
  { $set: { 'competitors.$': req.body, }, },
  (err, result) => {
    if (err) {
      res.status(500)
      .json({ error: 'Unable to update competitor.', });
    } else {
      res.status(200)
      .json(result);
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

我把我的HTTP PUTlocalhost:3000/competitors/577fe7a842c9bd6d更新彼得的银徽章.请求正文是:

{
  "name": "McDonald's"
}
Run Code Online (Sandbox Code Playgroud)

问题在于,当我$set用来设置竞争对手时_id: req.params.competitorId,我不知道它是什么req.body.我想使用整个req.body来更新数组中的对象,但是当我这样做时,该对象被覆盖,因此Peter的Silver Badges不会获得新名称,而是变成:

{
  name: 'McDonald\'s',
  sites: []
}
Run Code Online (Sandbox Code Playgroud)

当我知道_id具有所有字段的对象req.body而不删除我想要保留的字段时,如何更新数组中的对象?

我相信该sites数组是空的,因为该对象已重新初始化.在我的架构中,我必须sites: [sitesSchema]初始化它.所以我假设整个competitors[_id]对象被新名称覆盖,然后是sites: [sitesSchema]来自myschema.

小智 9

你需要使用你的$位置运算符$set.为了根据您的内容动态分配这些属性req.body,您需要以$set编程方式构建.

如果要更新名称,请执行以下操作:

Location.update(
  { 'competitors._id': req.params.competitorId },
  { $set:  { 'competitors.$.name': req.body.name }},
  (err, result) => {
    if (err) {
      res.status(500)
      .json({ error: 'Unable to update competitor.', });
    } else {
      res.status(200)
      .json(result);
    }
 }
);
Run Code Online (Sandbox Code Playgroud)

您可以以编程方式构建$set使用的一种方法req.body是执行以下操作:

let updateObj = {$set: {}};
for(var param in req.body) {
  updateObj.$set['competitors.$.'+param] = req.body[param];
 }
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅答案.