131

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

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

12 回答 12

215

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

Person.update({'items.id': 2}, {'$set': {
    'items.$.name': 'updated item2',
    'items.$.value': 'two updated'
}}, function(err) { ...
于 2013-03-28T20:54:08.183 回答
38
model.update(
    { _id: 1, "items.id": "2" },
    {
        $set: {
            "items.$.name": "yourValue",
            "items.$.value": "yourvalue",
         }
    }
)

MongoDB 文档

于 2017-03-14T03:56:47.023 回答
20

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

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')
});
于 2019-07-16T17:12:31.373 回答
10

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

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

这是文档

于 2019-05-29T10:08:24.673 回答
6

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

{'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}
于 2013-03-28T20:55:29.293 回答
4

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

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 }]

更多用法可以在官方文档中找到。

于 2020-04-29T03:52:12.990 回答
0

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

db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})
于 2017-01-27T14:52:59.203 回答
0

尝试过其他效果很好的解决方案,但他们的答案的陷阱是只有已经存在的字段会更新,添加 upsert 不会做任何事情,所以我想出了这个。

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
于 2020-02-26T17:36:28.760 回答
0

我有类似的问题。这是最干净的方法。

    const personQuery = {
       _id: 1  
    }

    const itemID = 2;

    Person.findOne(personQuery).then(item => {
       const audioIndex = item.items.map(item => item.id).indexOf(itemID);
       item.items[audioIndex].name = 'Name value';
       item.save();
    });
于 2020-12-12T10:33:45.463 回答
0

使用点对象找到了这个解决方案,它帮助了我。

import dot from "dot-object";

const user = await User.findByIdAndUpdate(id, { ...dot.dot(req.body) });
于 2021-12-10T16:17:37.237 回答
-1

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

user.updateInfoByIndex(0,"test")

User.methods.updateInfoByIndex = function(index, info) ={
    this.arrayField[index]=info
    this.save()
}
于 2017-09-07T07:59:09.270 回答
-1
update(
    {_id: 1, 'items.id': 2},
    {'$set': {'items.$[]': update}},
    {new: true})

这是有关以下内容的文档$[]https://docs.mongodb.com/manual/reference/operator/update/positional-all/#up。年代[]

于 2018-08-13T13:31:20.223 回答