42

我正在尝试遍历此循环:

for doc in coll.find()

我在第 100,000 条记录中收到以下错误。

File "build\bdist.win32\egg\pymongo\cursor.py", line 703, in next
File "build\bdist.win32\egg\pymongo\cursor.py", line 679, in _refresh
File "build\bdist.win32\egg\pymongo\cursor.py", line 628, in __send_message
File "build\bdist.win32\egg\pymongo\helpers.py", line 95, in _unpack_response
pymongo.errors.OperationFailure: cursor id '1236484850793' not valid at server

这个错误是什么意思?

4

5 回答 5

38

也许您的光标在服务器上超时。要查看这是否是问题所在,请尝试设置 timeout=False`:

for doc in coll.find(timeout=False)

http://api.mongodb.org/python/1.6/api/pymongo/collection.html#pymongo.collection.Collection.find

如果是超时问题,一种可能的解决方案是设置batch_size(s. other answers)。

于 2012-04-24T13:05:00.380 回答
36
  • 设置timeout=False是危险的,永远不要使用,因为与游标的连接可以无限期保持打开状态,这会影响系统性能。文档特别提到了手动关闭光标的需要。
  • 将 设置batch_size为较小的数字会起作用,但会产生很大的延迟问题,因为我们需要比需要更频繁地访问数据库。
    例如:
    小批量的 500 万个文档需要数小时才能检索到默认 batch_size 在几分钟内返回的相同数据。

在我的解决方案中,必须在光标上使用排序:

done = False
skip = 0
while not done:
    cursor = coll.find()
    cursor.sort( indexed_parameter ) # recommended to use time or other sequential parameter.
    cursor.skip( skip )
    try:
        for doc in cursor:
            skip += 1
            do_something()
        done = True
    except pymongo.errors.OperationFailure, e:
        msg = e.message
        if not (msg.startswith("cursor id") and msg.endswith("not valid at server")):
            raise
于 2013-10-01T13:34:15.507 回答
26

设置timeout=False是一种非常糟糕的做法。摆脱 cursor id 超时异常的更好方法是估计您的循环在 10 分钟内可以处理多少个文档,并得出一个保守的批量大小。这样,只要前一批中的文档用完,MongoDB 客户端(在本例中为 PyMongo)就必须不时地查询服务器。这将使光标在服务器上保持活动状态,并且您仍将受到 10 分钟超时保护的保护。

以下是设置游标批量大小的方法:

for doc in coll.find().batch_size(30):
    do_time_consuming_things()
于 2013-07-14T21:36:50.757 回答
0

你应该选择一个较低的 batch_size 值来解决这个问题:

col.find({}).batch_size(10)

看下面的答案

于 2017-08-01T23:45:34.883 回答
-1

您还可以使用以下命令强制评估:

for doc in list(coll.find())
于 2015-11-27T18:37:42.777 回答