【问题标题】:Update all elements in an array in mongodb [duplicate]更新mongodb中数组中的所有元素[重复]
【发布时间】:2016-01-16 03:47:27
【问题描述】:

我有一个 mongodb 文档,例如:

{
    "name" : "JohnDoe",
    "adds" : [
        {
            "status" : "PENDING",
            "date" : "2015-09-23"
        },
        {
            "status" : "PENDING",
            "date" : "2015-10-01"
        }
    ]
}

我想更新所有元素数组,例如:

collection.update({'name':'JohnDoe'}, {'$set':{'adds.status':'APPROVED'}}).

怎么做?

编辑:大多数解决方案说使用位置运算符选择数组元素,然后使用运算符更新该元素。但就我而言,我必须更新数组中的每个元素。

【问题讨论】:

  • @sheilak 我发帖用户可以选择一个单独的数组元素,然后他可以使用位置运算符更新它。但我必须更新数组中的每一个元素。
  • 该问题的答案说明您无法在一次更新中对数组中的所有项目执行 $set。接受的答案链接到关于该问题的开放 JIRA 票证。还发布了多种解决方法。

标签: mongodb


【解决方案1】:

如前所述,这里的主要问题是使用位置运算符更新多个元素,如这个长期存在的问题中所述:http://jira.mongodb.org/browse/SERVER-1243

因此,基本情况是没有单一的执行可以做到这一点,因此为了处理多个数组元素,您需要某种方法来确定需要更新多少元素并为每个元素处理一个更新语句。

对此的一种简化方法通常是使用Bulk Operations 将最终“多次”更新操作作为单个请求和对服务器的响应进行处理:

var bulk = db.collection.initializeOrderedBulkOp(),
    count = 0;

db.collection.find({ "name": "John Doe", "adds.status": "PENDING" }).forEach(function(doc) { 
    doc.adds.filter(function(add){ return add.status = "PENDING" }).forEach(function(add) {
        bulk.find({ "_id": doc._id, "adds.status": "PENDING" }).updateOne({
            "$set": { "adds.$.status": "APPROVED" }
        });
        count++;

        // Execute once in 1000 statements created and re-init
        if ( count % 1000 == 0 ) {
            bulk.execute();
            bulk = db.collection.initializeOrderedBulkOp();
        }
    });
});

// Execute any pending operations
if ( count % 1000 != 0 )
    bulk.execute();

如果您更新的文档非常小,或者实际上只有一个文档,那么您可以放弃count 检查,只需将所有批量更新附加到所需的循环中,并在所有循环结束时执行一次。

可以在How to Update Multiple Array Elements 上找到更长的解释和替代方法,但所有这些都归结为匹配元素以更新和处理positional $ 更新多次的不同方法,对于每个匹配的文档或直到没有更多的文档修改后的文件返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-14
    • 2018-02-19
    • 1970-01-01
    • 2020-04-18
    • 2021-05-16
    • 2013-09-07
    • 2017-01-05
    • 2020-03-16
    相关资源
    最近更新 更多