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

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

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

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

我试过以下方法:

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().
});
215386 次浏览

很接近了; 在使用 $更新操作员时应该使用点符号来实现这一点:

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

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

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

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

db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})
model.update(
{ _id: 1, "items.id": "2" },
{
$set: {
"items.$.name": "yourValue",
"items.$.value": "yourvalue",
}
}
)

MongoDB 文件

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

user.updateInfoByIndex(0,"test")


User.methods.updateInfoByIndex = function(index, info) ={
this.arrayField[index]=info
this.save()
}
update(
{_id: 1, 'items.id': 2},
{'$set': {'items.$[]': update}},
{new: true})

这是关于 $[]: https://docs.mongodb.com/manual/reference/operator/update/positional-all/#up.S[]的文件

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

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

这是 医生

有一种猫鼬式的做法。

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

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

 Person.update({'items.id': 2}, {$set: {
'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert:
true })

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

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

官方文件中可以找到更多的用法。

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

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

使用 dot-object 找到了这个解决方案,它帮助了我。

import dot from "dot-object";


const user = await User.findByIdAndUpdate(id, { ...dot.dot(req.body) });

我需要用动态键值对更新数组元素。 通过 测绘更新对象到包含 $更新操作符的新键,我不再必须知道数组元素的更新键,而是动态组装一个新的更新对象。

update = {
name: "Andy",
newKey: "new value"
}
new_update = Object.fromEntries(
Object.entries(update).map(
([k, v], i) => ["my_array.$." + k, v]
)
)
console.log({
"$set": new_update
})

使用 findOneAndUpdate清洁溶液

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