我试图按文档读取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溢出? 请建议我这样做的最佳方式。
感谢
答案 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
因为您的进程可能会崩溃并使集合处于半更新状态。您可能希望能够恢复它。
如果这是非分片集合的一次性作业,请考虑使用快照查询。