【问题标题】:Unordered bulk update records in MongoDB shellMongoDB shell中的无序批量更新记录
【发布时间】:2017-01-31 00:36:08
【问题描述】:

我有一个包含数百万个文档的集合,类似于以下内容:

{
    _id: ObjectId('...'),
    value: "0.53"
    combo: [
        {
            h: 0,
            v: "0.42"
        },
        {
            h: 1,
            v: "1.32"
        }
    ]
}

问题是值存储为字符串,我需要将它们转换为浮点数/双精度值。

我正在尝试这个并且它正在工作,但考虑到数据量,这需要几天才能完成:

db.collection.find({}).forEach(function(obj) { 
    if (typeof(obj.value) === "string") {
        obj.value = parseFloat(obj.value);
        db.collection.save(obj);
    }

     obj.combo.forEach(function(hv){
         if (typeof(hv.value) === "string") {
            hv.value = parseFloat(hv.value);
            db.collection.save(obj);
         }
     });
});

我在阅读 Mongo 文档时遇到了批量更新,我正在尝试这个:

var bulk = db.collection.initializeUnorderedBulkOp();
bulk.find({}).update(
    { 
      $set: { 
                "value": parseFloat("value"), 
            }
    });
bulk.execute();

这运行...但我得到一个 NAN 作为值,这是因为它认为我正在尝试将“值”转换为浮点数。我尝试了不同的变体,如this.value"$value",但无济于事。另外,这种方法只尝试更正另一个对象中的值,而不是数组中的值。

如果有任何帮助,我将不胜感激。提前致谢!

【问题讨论】:

    标签: mongodb mongo-shell


    【解决方案1】:

    通过以下方式解决:

    1)为了在文档级别进行转换,我遇到了this post,Markus 的回复为我的解决方案铺平了道路:

    var bulk = db.collection.initializeUnorderedBulkOp()
    var myDocs = db.collection.find()
    var ops = 0
    myDocs.forEach(
    
      function(myDoc) {
    
        bulk.find({ _id: myDoc._id }).updateOne(
            { 
              $set : {
                    "value": parseFloat(myDoc.value),
                } 
            }
        );
    
        if ((++ops % 1000) === 0){
          bulk.execute();
          bulk = db.collection.initializeUnorderedBulkOp();
        }
    
      }
    )
    bulk.execute();
    

    2) 第二部分涉及更新数组对象值,我在this post 上接受的答案中发现了这样做的语法。就我而言,我知道有 24 个值在我与第一个查询分开运行时,结果如下所示:

    var bulk = db.collection.initializeUnorderedBulkOp()
    var myDocs = db.collection.find()
    var ops = 0
    myDocs.forEach(
    
      function(myDoc) {
    
        bulk.find({ _id: myDoc._id }).update(
            { 
              $set : { 
                    "combo.0.v": parseFloat(myDoc.combo[0].v),
                    "combo.1.v": parseFloat(myDoc.combo[1].v),
                    "combo.2.v": parseFloat(myDoc.combo[2].v),
                    "combo.3.v": parseFloat(myDoc.combo[3].v),
                    "combo.4.v": parseFloat(myDoc.combo[4].v),
                    "combo.5.v": parseFloat(myDoc.combo[5].v),
                    "combo.6.v": parseFloat(myDoc.combo[6].v),
                    "combo.7.v": parseFloat(myDoc.combo[7].v),
                    "combo.8.v": parseFloat(myDoc.combo[8].v),
                    "combo.9.v": parseFloat(myDoc.combo[9].v),
                    "combo.10.v": parseFloat(myDoc.combo[10].v),
                    "combo.11.v": parseFloat(myDoc.combo[11].v),
                    "combo.12.v": parseFloat(myDoc.combo[12].v),
                    "combo.13.v": parseFloat(myDoc.combo[13].v),
                    "combo.14.v": parseFloat(myDoc.combo[14].v),
                    "combo.15.v": parseFloat(myDoc.combo[15].v),
                    "combo.16.v": parseFloat(myDoc.combo[16].v),
                    "combo.17.v": parseFloat(myDoc.combo[17].v),
                    "combo.18.v": parseFloat(myDoc.combo[18].v),
                    "combo.19.v": parseFloat(myDoc.combo[19].v),
                    "combo.20.v": parseFloat(myDoc.combo[20].v),
                    "combo.21.v": parseFloat(myDoc.combo[21].v),
                    "combo.22.v": parseFloat(myDoc.combo[22].v),
                    "combo.23.v": parseFloat(myDoc.combo[23].v)
              }
            }
        );
    
        if ((++ops % 1000) === 0){
          bulk.execute();
          bulk = db.collection.initializeUnorderedBulkOp();
        }
    
      }
    )
    bulk.execute();
    

    就性能而言,forEach 每分钟处理大约 900 个文档,对于 1500 万条记录,这实际上需要几天时间!不仅如此,这只是在文档级别转换类型,而不是数组级别。为此,我必须遍历每个文档并遍历每个数组(1500 万 x 24 次迭代)!使用这种方法(同时运行两个查询),它在 6 小时内完成。

    我希望这对其他人有帮助。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 2011-05-25
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2019-01-02
    相关资源
    最近更新 更多