【问题标题】:Iterating over MongoDB collection to duplicate all documents is painfully slow迭代 MongoDB 集合以复制所有文档非常缓慢
【发布时间】:2017-11-06 20:24:37
【问题描述】:

我想复制一个 MongoDB 集合中的 7,000,000 个文档(每个文档可能 1-2 KB BSON),修改一个字段。该字段是一个带有数值的字符串,我想将该字段增加1。

按照 this approach 从 Mongo shell,我采取了以下方法:

> var all = db.my_collection.find()
> all.forEach(function(it) { 
... it._id = 0; // to force mongo to create a new objectId
... it.field = (parseInt(it.field) + 1).toString();
... db.my_collection.insert(it);
... })

执行以下代码需要很长时间;起初我以为代码以某种方式被破坏了,但是我在一个单独的终端上检查了大约一个小时后的集合状态,发现该过程仍在运行,现在有 7,000,001 个文档!我查了一下,果然有 1 个新文档与增加的字段相匹配。

就上下文而言,我正在运行具有 4 个内核和 16 GB 内存的 2015 MBP。我看到mongo 接近我的 CPU 开销的顶部,平均约为 85%。

1) 我是否缺少 Mongodb 中的批量修改/更新功能?

2) 为什么上述操作可以正常工作,但工作速度太慢以至于它以 1/hr 的速度更新文档?

【问题讨论】:

    标签: mongodb mongo-shell


    【解决方案1】:

    试试db.collection.mapReduce()的方式:

    注意:单个发射只能容纳 MongoDB 最大 BSON 文档大小的一半。

    var mapFunction1 = function() {
                           emit(ObjectId(), (parseInt(this.field) + 1).toString());
                       };
    

    MongoDB 不会为只有一个值的键调用 reduce 函数。

    var reduceFunction1 = function(id, field) {
                              return field;
                          };
    

    最后,

    db.my_collection.mapReduce(
    mapFunction1,
    reduceFunction1.
    {"out":"my_collection"} //Replaces the entire content; consider merge
    )
    

    【讨论】:

    • 您能否详细说明“考虑合并”?
    • 对于这种情况,**replace ** 发生(默认情况下)并且集合的全部内容被 reduce() 的输出替换。写入 {"out":{merge:"my_collection"}} 将替换现有的匹配键并覆盖它们。
    【解决方案2】:

    不好意思说我误会了这一行:

    ... it._id = 0; // to force mongo to create a new objectId
    

    确实强制 mongo 创建一个新的 ObjectId。相反,我需要成为explicit

    ... it._id = ObjectId();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-23
      • 2014-03-08
      • 2021-03-30
      • 2017-02-11
      • 2016-10-07
      • 2020-10-05
      • 2014-04-02
      • 1970-01-01
      相关资源
      最近更新 更多