我有一个简单的单客户端设置MongoDB和PyMongo 2.6.3.目标是迭代集合中的每个文档collection
并更新(save
)过程中的每个文档.我正在使用的方法大致如下:
cursor = collection.find({}) index = 0 count = cursor.count() while index != count: doc = cursor[index] print 'updating doc ' + doc['name'] # modify doc .. collection.save(doc) index += 1 cursor.close()
问题是save
显然正在修改游标中文档的顺序.例如,如果我的集合由3个文档组成(id
为清楚起见,省略了):
{ "name": "one" } { "name": "two" } { "name": "three" }
上述计划产出:
> updating doc one > updating doc two > updating doc two
但是,如果collection.save(doc)
删除该行,则输出变为:
> updating doc one > updating doc two > updating doc three
为什么会这样?安全地迭代和更新集合中的文档的正确方法是什么?
在MongoDB 文档中找到答案:
由于游标在其生命周期内未被隔离,因此对文档进行干预写入操作可能会导致光标在文档发生更改时多次返回文档.要处理此情况,请参阅有关快照模式的信息.
光标上启用了快照模式,这是一个很好的保证:
snapshot()
遍历_id
字段上的索引并保证查询将返回每个文档(相对于_id
字段的值)不超过一次.
要使用PyMongo启用快照模式:
cursor = collection.find(spec={},snapshot=True)
根据PyMongo find()
文档.确认这解决了我的问题.
快照完成工作.
但是在pymongo 2.9和之后,语法略有不同.
cursor = collection.find(modifiers={"$snapshot": True})
或任何版本,
cursor = collection.find({"$snapshot": True})
根据PyMongo文档