【问题标题】:Bulk update in Pymongo using multiple ObjectId使用多个 ObjectId 在 Pymongo 中批量更新
【发布时间】:2016-05-30 13:42:54
【问题描述】:

我想更新 mongo 集合中的数千个文档。我想使用 ObjectId 找到它们,然后无论哪个文档匹配,都应该更新。我对所有文件的更新都是一样的。我有 ObjectId 的列表。对于列表中的每个 ObjectId,mongo 应该找到匹配的文档并将该文档的“isBad”键更新为“N”

ids = [ObjectId('56ac9d3fa722f1029b75b128'), ObjectId('56ac8961a722f10249ad0ad1')]
bulk = db.testdata.initialize_unordered_bulk_op()
bulk.find( { '_id': ids} ).update( { '$set': {  "isBad" : "N" } } )
print bulk.execute()

这给了我结果:

{'nModified': 0, 'nUpserted': 0, 'nMatched': 0, 'writeErrors': [], 'upserted': [], 'writeConcernErrors': [], 'nRemoved': 0, 'nInserted': 0}

这是预期的,因为它试图将“_id”与列表匹配。但我不知道如何继续。

我知道如何单独更新每个文档。我的列表大小约为 25000。我不想单独拨打 25000 个电话。我收藏的文档数量要多得多。我正在使用 python2,pymongo = 3.2.1。

【问题讨论】:

    标签: python mongodb python-2.7 pymongo pymongo-3.x


    【解决方案1】:
    bulk = db.testdata.initialize_unordered_bulk_op()
    
    for id in ids:
       bulk.find( { '_id':  id}).update({ '$set': {  "isBad" : "N" }})
    
    bulk.execute()
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    【解决方案2】:

    使用 for 循环遍历 id 列表并以 500 个批量发送批量更新:

    bulk = db.testdata.initialize_unordered_bulk_op()
    counter = 0
    
    for id in ids:
        # process in bulk
        bulk.find({ '_id': id }).update({ '$set': { 'isBad': 'N' } })
        counter += 1
    
        if (counter % 500 == 0):
            bulk.execute()
            bulk = db.testdata.initialize_ordered_bulk_op()
    
    if (counter % 500 != 0):
        bulk.execute()
    

    因为写命令可以接受不超过 1000 个操作(来自 docs),您必须将批量操作拆分为多个批次,在这种情况下您可以选择任意批次大小最多 1000 个。

    之所以选择500,是为了保证Bulk.find()的关联文档与更新文档之和小于等于最大BSON文档大小,即使没有无法保证使用默认的 1000 个操作请求将符合 16MB BSON 限制。 mongo shell 中的 Bulk() 操作和驱动程序中的类似方法没有此限制。

    【讨论】:

    • 为什么限制为 500 ?
    • @chridam 我猜如果超过内存限制它会自动分成几部分。所以我认为,没有必要保持柜台。我说的对吗?
    • 无需拆分批量操作,pymongo 会负责:api.mongodb.com/python/current/examples/…
    【解决方案3】:

    我得到了答案,可以这样:

        bulk = db.testdata.initialize_unordered_bulk_op()
        for i in range (0, len(ids)):
            bulk.find( { '_id':  ids[i]}).update({ '$set': {  "isBad" : "N" }})
        print bulk.execute()
    

    【讨论】:

    • 你为什么需要range这太低效了。
    猜你喜欢
    • 2017-07-12
    • 2020-07-10
    • 2014-12-13
    • 2013-04-11
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多