2016-07-08 3 views
2

У меня есть объект, который выглядит так.Node.js - Mongoose - Обновить вложенный массив со всеми значениями в req.body

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

Моя цель состоит в том, чтобы ссылаться на competitors массив и обновление элементов внутри со всеми значениями из req.body. Я основывал этот код на this ответах, а также 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); 
    } 
    } 
); 

Я посылаю мой HTTP PUT в localhost:3000/competitors/577fe7a842c9bd6d обновить серебряные значки Питера. Тело запроса:

{ 
    "name": "McDonald's" 
} 

Проблема заключается в том, что, когда я использую $set установить конкурент с _id: req.params.competitorId, я не знаю, что в req.body. Я хочу использовать весь req.body для обновления объекта в массиве, но когда я делаю, что объект перезаписывается, поэтому вместо того, чтобы получить новое имя, Питер Серебро Жетоны становится:

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

Как я могу обновить объект в массиве, когда я знаю объект _id со всеми полями от req.body без удаления полей, которые я хочу сохранить?

Я считаю, что массив sites пуст, потому что объект был повторно инициализирован. В моей схеме у меня есть sites: [sitesSchema], чтобы инициализировать его. Поэтому я предполагаю, что весь объект competitors[_id] будет перезаписан новым именем, а затем sites: [sitesSchema] из myschema.

ответ

6

Вам необходимо будет использовать операционный оператор $ в вашем $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); 
    } 
} 
); 

Один из способов вы можете программно наращивать $set с помощью req.body, делая следующее:

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

См this ответьте для более подробной информации.

0

Для обновления встроенного документа с помощью оператора $ в большинстве случаев вам необходимо использовать точечную нотацию в операторе $.

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); 
    } 
    } 
); 
Смежные вопросы