最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Node.js - Mongoose - Update nested array with all values in req.body - Stack Overflow

programmeradmin3浏览0评论

I have an object that looks like this.

{
  _id: '577fe7a842c9b447',
  name: 'Jacob\'s Bronze Badges',
  competitors: [
    {
      _id: '577fe7a842c9bd6d',
      name: 'Peter\'s Silver Badges',
      sites: [
        {
          _id: '577fe7a842c9bd6d',
          name: 'Facebook',
          url: 'fb/peter'
        },
        {
          _id: '577fe7a842c9bd6d'
          name: 'Google',
          url: 'google/peter'
        }
      ]
    },
    {
      _id: '599fe7a842c9bd6d',
      name: 'Paul\'s Gold Badges',
      sites: [
        {
          '_id': '577fe7a842c9bd6d',
          name: 'Facebook',
          url: 'fb/paul'
        },
        {
          _id: '577fe7a842c9bd6d',
          name: 'Google',
          url: 'google/paul'
        }
      ]
    }
  ]
}

My goal is to reference the competitors array and update items inside with all of the values from req.body. I based this code off of this answer, as well as this other one.

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

I send my HTTP PUT to localhost:3000/competitors/577fe7a842c9bd6d to update Peter's Silver Badges. The request body is:

{
  "name": "McDonald's"
}

The problem is that when I use $set to set the competitor with _id: req.paramspetitorId, I don't know what is in req.body. I want to use the entire req.body to update the object in the array, but when I do, that object is overwritten, so instead of getting a new name, Peter's Silver Badges becomes:

{
  name: 'McDonald\'s',
  sites: []
}

How can I update an object within an array when I know the object's _id with all of the fields from req.body without removing fields that I want to keep?

I believe that the sites array is empty because the object was reinitialized. In my schema I have sites: [sitesSchema] to initialize it. So I am assuming that the whole competitors[_id] object is getting overwritten with the new name and then the sites: [sitesSchema] from myschema.

I have an object that looks like this.

{
  _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'
        }
      ]
    }
  ]
}

My goal is to reference the competitors array and update items inside with all of the values from req.body. I based this code off of this answer, as well as this other one.

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);
    }
  }
);

I send my HTTP PUT to localhost:3000/competitors/577fe7a842c9bd6d to update Peter's Silver Badges. The request body is:

{
  "name": "McDonald's"
}

The problem is that when I use $set to set the competitor with _id: req.params.competitorId, I don't know what is in req.body. I want to use the entire req.body to update the object in the array, but when I do, that object is overwritten, so instead of getting a new name, Peter's Silver Badges becomes:

{
  name: 'McDonald\'s',
  sites: []
}

How can I update an object within an array when I know the object's _id with all of the fields from req.body without removing fields that I want to keep?

I believe that the sites array is empty because the object was reinitialized. In my schema I have sites: [sitesSchema] to initialize it. So I am assuming that the whole competitors[_id] object is getting overwritten with the new name and then the sites: [sitesSchema] from myschema.

Share Improve this question edited May 23, 2017 at 12:16 CommunityBot 11 silver badge asked Jul 8, 2016 at 19:28 JacobJacob 1,5785 gold badges19 silver badges41 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 14

You would need to use the $ positional operator in your $set. In order to assign those properties dynamically, based on what is in your req.body, you would need to build up your $set programmatically.

If you want to update the name you would do the following:

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);
    }
 }
);

One way you might programatically build up the $set using req.body is by doing the following:

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

See this answer for more details.

To update embedded document with $ operator, in most of the cases, you have to use dot notation on the $ operator.

Location.update(
  { _id: '577fe7a842c9b447', '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);
    }
  }
);
发布评论

评论列表(0)

  1. 暂无评论