使用pymongo读取和更新mongodb文档的最佳方法

时间:2014-08-25 11:36:39

标签: python mongodb pymongo mongodb-query

我试图按文档读取mongodb集合文档,以便获取每条记录,加密记录中的某些字段并将其放回数据库。

for record in coll.find():
    #modifying record here
    coll.update(record)

这导致严重的问题,即已经更新的文档被光标再次读取,同一文档再次被循环处理(同一文档试图再次更新)

希望这可能是解决问题的方法之一。

list_coll = [record for record in coll.find()]
for rec in list_coll:
   #modifying record
   coll.update(rec)

但这是最好的做法吗?即如果集合很大会发生什么?可以大的list_coll导致ram溢出? 请建议我这样做的最佳方式。

感谢

3 个答案:

答案 0 :(得分:8)

你想要来自MongoDB的"Bulk Operations API"。主要是MongoDB 2.6引入的,所以如果你现在还没有升级的话,这是一个令人信服的理由。

bulk = db.coll.initialize_ordered_bulk_op()
counter = 0

for record in coll.find(snapshot=True):
    # now process in bulk
    # calc value first
    bulk.find({ '_id': record['_id'] }).update({ '$set': { 'field': newValue } })
    counter += 1

    if counter % 1000 == 0:
        bulk.execute()
        bulk = db.coll.initialize_ordered_bulk_op()

if counter % 1000 != 0:
    bulk.execute()

好多了,因为您没有向服务器发送“每个”请求,每1000个请求只发送一次。 “批量API”实际上对你有所帮助,但实际上你想要“管理”这个更好一些,而不是在你的应用程序中消耗太多内存。

未来之路。使用它。

答案 1 :(得分:3)

如果您的收藏品没有分片,则可以使用snapshot参数将find光标与更新后的for record in coll.find(snapshot = True): #modifying record here coll.update(record) 光标隔离后再次隔离:

_id

如果您的集合是分片的,请保留已更新的{{1}}值的哈希变量,然后在修改每条记录之前检查该列表,以确保不会更新相同的两次。< / p>

答案 2 :(得分:0)

将每条记录标记为已更新,例如通过添加标志或确保更新的字段具有可由查询匹配的特定表单。

使用查询仅匹配尚未更新的文档,并在迭代时仔细检查每个文档。

为什么?

  • 因为集合可能太大而无法管理本地哈希中的更新ID

  • 因为您的进程可能会崩溃并使集合处于半更新状态。您可能希望能够恢复它。

如果这是非分片集合的一次性作业,请考虑使用快照查询。