更新嵌套数组中的多个对象

Updating a number of objects in a nested array

本文关键字:对象 嵌套 数组 更新      更新时间:2023-09-26

假设我们有这个文档:

{
    "_id" : ObjectId("4faaba123412d654fe83hg876"),
    "items" : [
            {
                    "name" : "item_one",
                    "bought" : true
            },
            {
                    "name" : "my_item",
                    "bought" : true
            },
            {
                    "name" : "my_item_three",
                    "bought" : true
            }
    ]
}

例如,我如何修改数组的前 2 个对象并将其"购买"设置为 false。或者换句话说,我如何更改前 n 个对象的属性。

我想我可以先用这个 ID 做一个db.findOne(),然后获取项目并使用一个将更改值的函数,然后将整个项目设置为该函数返回的这个新数组。

这可能会完成这项工作,但有没有更快更好的方法?如果我知道要更改的对象数量,有没有办法做到这一点,因此例如它不会是 n 而是 5。

您可以遍历所需的第 n 个对象,并使用 '=' 将购买设置为 false:

for(var i=0; i < n_times; i++){  
    my_object.items[i].bought = false;
}

如果您事先知道要更新的对象数量,那么可以利用更新中的点表示法通过循环访问数组的元素:

var id = ObjectId("4faaba123412d654fe83hg876");
// Iterate and update using the update query object 
for(var i=0; i<n; i++){ 
    var update = { "$set": {} };
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;
    db.collection.update({"_id": id}, update, {"upsert": false, "multi": true});
}

--

编辑 --

这也可以在一次原子更新中完成,假设您在更新之前创建了更新对象,如下所示

var update = { "$set": {} };
for(var i=0; i<n; i++){ 
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;    
}
db.collection.update({"_id": id}, update, {"upsert": false, "multi": true});

查看下面的演示

var update = { "$set": {} };
for(var i=0; i<5; i++){ 
    // set the update query object
    update["$set"]["items."+i.toString()+".bought"] = false;    
}
pre.innerHTML = JSON.stringify(update);
<pre id="pre"></pre>