【问题标题】:How to iterate and update documents with PyMongo?如何使用 PyMongo 迭代和更新文档?
【发布时间】:2013-12-15 07:52:53
【问题描述】:

我有一个简单的 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 个文档组成(为清楚起见,省略了 ids):

{
    "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

为什么会这样?安全地迭代更新集合中的文档的正确方法是什么?

【问题讨论】:

  • 这不是答案。但是试试1 + 999 is 1000 和``1 + 999 == 1000`。
  • @falsetru thx 只是为了简单而重新创建,仍在学习 python :)。现在好吗?
  • 你是如何修改文档的? doc['name'] = 'newValue'够了吗?

标签: python mongodb pymongo


【解决方案1】:

在MongoDBdocumentation找到答案:

由于游标在其生命周期内没有被隔离,因此对文档进行干预写入操作可能会导致游标在文档发生更改时多次返回该文档。要处理这种情况,请参阅snapshot mode 上的信息。

在光标上启用快照模式,并做出很好的保证:

snapshot() 遍历_id 字段上的索引,并保证查询将返回每个文档(相对于_id 字段的值)不超过一次。

使用 PyMongo 启用快照模式:

cursor = collection.find(spec={},snapshot=True)

根据 PyMongo find() documentation。确认这解决了我的问题。

【讨论】:

【解决方案2】:

快照可以完成这项工作。

但在 pymongo 2.9 及更高版本上,语法略有不同。

cursor = collection.find(modifiers={"$snapshot": True})

或任何版本,

cursor = collection.find({"$snapshot": True})

根据PyMongo documentations

【讨论】:

    【解决方案3】:

    我无法重现您的情况,但也许,在我的脑海中,因为像您正在做的那样获取结果会从数据库中一一获取,您实际上是在创建更多内容(保存然后获取下一个)。

    您可以尝试将结果保存在列表中(这样,您可以一次获取所有结果 - 可能很繁重,具体取决于您的查询):

    cursor = collection.find({})
    # index = 0
    results = [res for res in cursor] #count = cursor.count()
    cursor.close()
    for res in results: # while index != count //This will iterate the list without you needed to keep a counter:
        # doc = cursor[index] // No need for this since 'res' holds the current record in the loop cycle
        print 'updating doc ' + res['name'] # print 'updating doc ' + doc['name']
        # modify doc ..
        collection.save(res)
        # index += 1 // Again, no need for counter
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2021-06-22
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      相关资源
      最近更新 更多