猫鼬,更新对象数组中的值


94

有没有一种方法可以更新对象中的值?

{
  _id: 1,
  name: 'John Smith',
  items: [{
     id: 1,
     name: 'item 1',
     value: 'one'
  },{
     id: 2,
     name: 'item 2',
     value: 'two'
  }]
}

假设我要为id = 2的项更新名称和值项;

我尝试了以下w /猫鼬:

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

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

猫鼬中是否有更好的方法来设置数组中的某些值,但不理会其他值?

我也只问这个人:

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

Answers:


162

你近了 您应该在使用$更新运算符时使用点符号来做到这一点:

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

您好,当我确切地提出您的建议时。board.update({_id:board._id,“ users.username”:req.user.username},{$ set:{“ users。$。lastViewed”:new Date()}},函数(err){} ); 我收到一个错误消息:无法使用零件(users.username的用户)遍历元素({users:[{username:“ nlm”,_ id:ObjectId('583c8cc3813daa6c29f69cb0'),状态:“ invited”,角色:“评论者”“}]})。我做了什么不同的事情吗?
Peter Huang

4
效果很好,谢谢。但是,如果项目不在数组中,有什么方法可以创建它?
谢尔盖·梅尔

@SergeyMell,如果我认为这可能是一个解决方案:stackoverflow.com/a/33577318/6470918
GrzegorzBrzęczyszczykiewicz18年

如何更新集合中所有文档中id = 2的名称?
Rod

1
如果数组中有对象数组,这将如何工作?喜欢而不是仅仅items.$.name拥有items.users.$.status?那行得通吗?
Stevie Star,


11

有一种猫鼬的方法。

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

5

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

{'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}

3

要记住一件事,当您基于多个条件在数组中搜索对象时,请使用$ elemMatch

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

这是文档



1

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

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

请注意,通过这种方式,您可以通过添加其他arrayFilters类似方式来更新嵌套数组的更深层次:

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

"arrayFilters":[{ "outer.id": itemId },{ "inner.id": innerItemId }]

希望对您有所帮助。祝好运!


0

在猫鼬中我们可以更新,就像简单的数组

user.updateInfoByIndex(0,"test")

User.methods.updateInfoByIndex = function(index, info) ={
    this.arrayField[index]=info
    this.save()
}

4
您的回答将对某些解释有所帮助。请考虑对其进行编辑。
O. Jones

0

在Mongoose中,我们可以使用$set内部dot(.)表示法将数组值更新为特定值,方法如下

db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})

您可以编辑带说明的答案,还是与问题相关?
NIKHIL CM

1
您能不能看看我的问题,猫鼬被删除我的查询,它使用部分$ []即使它工作在CLI stackoverflow.com/questions/64223672/...
nrmad

0

尝试过其他效果很好的解决方案,但他们的答案的陷阱是,只有已经存在的字段会更新,向其中添加upsert不会起作用,因此我想到了这一点。

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.