Mongoose,更新对象数组中的值

los*_*ion 74 mongoose mongodb node.js

有没有办法更新对象中的值?

{
  _id: 1,
  name: 'John Smith',
  items: [{
     id: 1,
     name: 'item 1',
     value: 'one'
  },{
     id: 2,
     name: 'item 2',
     value: 'two'
  }]
}
Run Code Online (Sandbox Code Playgroud)

假设我想更新id = 2的项目的名称和值项目;

我尝试了以下w/mongoose:

var update = {name: 'updated item2', value: 'two updated'};
Person.update({'items.id': 2}, {'$set':  {'items.$': update}}, function(err) { ...
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于它更新/设置整个对象,因此在这种情况下我丢失了id字段.

有没有更好的方法在mongoose中设置数组中的某些值但是只留下其他值?

我也只是询问了这个人:

Person.find({...}, function(err, person) {
  person.items ..... // I might be able to search through all the items here and find item with id 2 then update the values I want and call person.save().
});
Run Code Online (Sandbox Code Playgroud)

Joh*_*yHK 125

你很亲密; 你应该使用点符号$来做到这一点:

Person.update({'items.id': 2}, {'$set': {
    'items.$.name': 'updated item2',
    'items.$.value': 'two updated'
}}, function(err) { ...
Run Code Online (Sandbox Code Playgroud)

  • 这很棒,谢谢.但是,有没有办法创建一个项目,如果它不在数组中? (4认同)
  • 如果数组中有一个对象数组,这将如何工作?就像不是只有“items.$.name”,而是“items.users.$.status”?那行得通吗? (2认同)

Ane*_*eed 18

有一种猫鼬的方法可以做到这一点。

const itemId = 2;
const query = {
  item._id: itemId 
};
Person.findOne(query).then(doc => {
  item = doc.items.id(itemId );
  item["name"] = "new name";
  item["value"] = "new value";
  doc.save();

  //sent respnse to client
}).catch(err => {
  console.log('Oh! Dark')
});
Run Code Online (Sandbox Code Playgroud)

  • 如果您要对父文档以及数组项进行操作,则此方法非常方便。 (2认同)

小智 12

model.update({"_id": 1, "items.id": "2"}, 
{$set: {"items.$.name": "yourValue","items.$.value": "yourvalue"}})
Run Code Online (Sandbox Code Playgroud)

Mongodb文件

  • 最好使用“updateOne”或“updateMany”,而不是“update” (7认同)

小智 9

有一件事要记住,当您根据多个条件搜索数组中的对象时,请使用$elemMatch

Person.update(
   {
     _id: 5,
     grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
   },
   { $set: { "grades.$.std" : 6 } }
)
Run Code Online (Sandbox Code Playgroud)

这是文档


Jak*_*cki 9

下面是如何更动态地更新对象数组中的值的示例。

Person.findOneAndUpdate({_id: id}, 
{ 
  "$set": {[`items.$[outer].${propertyName}`]: value} 
},
{ 
  "arrayFilters": [{ "outer.id": itemId }]
},
function(err, response) {
  ...
})
Run Code Online (Sandbox Code Playgroud)

请注意,通过这样做,您将能够通过添加附加的arrayFilters位置运算符来更新嵌套数组的更深层次,如下所示:

"$set": {[`items.$[outer].innerItems.$[inner].${propertyName}`]: value} 

"arrayFilters":[{ "outer.id": itemId },{ "inner.id": innerItemId }]
Run Code Online (Sandbox Code Playgroud)

更多用法可以查看官方文档


小智 6

对于每个文档,更新操作符$set可以设置多个值,因此items您可以单独设置对象的namevalue字段,而不是替换数组中的整个对象。

{'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}
Run Code Online (Sandbox Code Playgroud)


sam*_*war 6

使用更清洁的解决方案findOneAndUpdate

  await Person.findOneAndUpdate(
    { _id: id, 'items.id': 2 },
    {
      $set: {
        'items.$.name': 'updated item2', 
        'items.$.value': 'two updated',
      }
    },
   );
Run Code Online (Sandbox Code Playgroud)