【问题标题】:Mongo update using forEach is too slow使用 forEach 进行 Mongo 更新太慢
【发布时间】:2021-07-15 09:39:21
【问题描述】:

我有 2000 个文档,我想为每个文档添加一个新字段 (newUUID),并根据现有字段 (oldUUID) 设置其值。

我正在运行以下查询:

var cursor1 = db.myCollection.find();
cursor1.forEach(function(results){ db.myCollection.update({_id: results._id}, {$set: {newUUID: results.oldUUID}})})

但迭代需要很长时间

MongoDB服务器版本:3.6.0

MongoDB shell 版本 v4.4.1

【问题讨论】:

  • 从 MongoDB 4.2 开始,您可以使用 updateMany() 和聚合 docs.mongodb.com/manual/tutorial/…
  • 在 mongodb 3.6 版本中没有其他更新选项。
  • 改用bulkWrite 选项
  • @Ashh 听起来不错,但是如何在没有 Mongoose 的 Mongo shell 中做到这一点?
  • @AlexL 您要么需要使用仅在 4.2+ 中可用的查询进行更新,要么需要使用您正在使用的语言编写某种代码..

标签: mongodb


【解决方案1】:

如果您使用的是 Mongo 4.2+ 版,您可以使用pipelined updates

db.collection.updateMany(
{},
[
  {
    "$set": {
      "newUUID": "$oldUUID"
    }
  }
])

Mongo Playground

对于较小的 Mongo 版本,无法使用自己的值更新文档(除非您想使用 $out 之类的东西),因此您必须将其读入内存并更新每个代码。

【讨论】:

    【解决方案2】:

    我设法通过以下方式解决了这个问题:我制作了一个使用 bulk_write 的 python 脚本,尽管 真正 问题是我使用的 find 方法 - 我正在使用它没有过滤器。

    脚本:

    import pymongo
    from pymongo import UpdateOne
    import time
    
    conn = pymongo. MongoClient("mongodb://localhost",
                                 username='',
                                 password='',
                                 tls=False, tlsCAFile=None)
    db = conn.some_db
    collection = db['myCollection']
    
    
    start_time = time.time()
    operations = []
    updated = 0
    
    for doc in collection.find({}, {'_id': 1, 'oldUuid': 1}):
        operations.append(
            UpdateOne({"_id": doc["_id"]}, {"$set": {"newUUID": doc["oldUuid"]}})
        )
    
        # Send once every 1000 in batch
        if len(operations) == 1000:
            collection.bulk_write(operations, ordered=False)
            updated += len(operations)
            operations = []
            print("updated 1000")
    
    if len(operations) > 0:
        collection.bulk_write(operations, ordered=False)
        updated += len(operations)
    
    processed_time = time.time() - start_time
    
    print(f"Updated {updated} documents")
    
    print(f"The operation took {processed_time} seconds")
    print(f"The operation took {processed_time/60} minutes")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 2021-12-14
      • 2019-07-19
      • 1970-01-01
      • 2011-09-07
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多