mongodb光标ID无效错误

我正在尝试遍历这个循环:

for doc in coll.find() 

我在第100,000条logging上得到以下错误。

 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 

这个错误是什么意思?

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

 for doc in coll.find(timeout=False) 

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

如果是超时问题,一个可能的解决scheme是设置batch_size (其他答案)。

  • 设置timeout=False是危险的,不应该使用,因为连接到游标的时间可以保持无限,这会影响系统的性能。 该文档特别引用需要手动closures游标。
  • batch_size设置为一个很小的数字将会起作用,但是会产生很大的延迟问题,因为我们需要比需要更频繁地访问数据库。
    例如:
    5M文档与一个小批量将需要几个小时来检索相同的数据,默认batch_size在几分钟内返回。

在我的解决scheme中,必须对光标进行sorting

 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 

设置timeout=False是一个非常糟糕的做法。 摆脱游标ID超时exception的一个更好的方法是估计循环可以在10分钟内处理多less个文档,并提出一个保守的批量大小。 这样,MongoDB客户端(在这种情况下,PyMongo)将不得不每隔一段时间查询服务器,只要上一批中的文档用完。 这将使光标在服务器上保持活动状态,并且您仍将被覆盖10分钟的超时保护。

以下是如何设置游标的批处理大小:

 for doc in coll.find().batch_size(30): do_time_consuming_things() 

您也可以使用以下方法强制评估:

 for doc in list(coll.find()) 

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

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

看到下面的答案