Подтвердить что ты не робот

Неверная ошибка курсора mongodb

Я пытаюсь выполнить итерацию через этот цикл:

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

что означает эта ошибка?

4b9b3361

Ответ 1

Возможно, ваш указатель на сервере отключен. Чтобы убедиться, что это проблема, попробуйте установить таймаут = 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).

Ответ 2

  • Установка timeout=False опасна и никогда не должна использоваться, поскольку соединение с курсором может оставаться открытым неограниченное время, что скажется на производительности системы. Документы специально указывают на необходимость вручную закрыть курсор.
  • Настройка batch_size на небольшое число будет работать, но создает большую проблему с задержкой, потому что нам нужно чаще обращаться к БД, чем нужно.
    Например:
    Документы 5M с небольшой партией будут занимать часы для извлечения те же данные, которые по умолчанию batch_size возвращает за несколько минут.

В моем решении обязательно использовать sort в курсоре:

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

Ответ 3

Настройка timeout=False - очень плохая практика. Лучший способ избавиться от исключения тайм-аута идентификатора курсора - оценить количество документов, которые ваш цикл может обрабатывать в течение 10 минут, и придумать консервативный размер партии. Таким образом, клиент MongoDB (в данном случае, PyMongo) будет запрашивать сервер один раз в то время, когда были израсходованы документы предыдущей партии. Это будет держать курсор активным на сервере, и вы все равно будете защищены 10-минутной тайм-аутом.

Вот как вы устанавливаете размер партии для курсора:

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

Ответ 4

Вы также можете принудительно выполнить оценку, используя:

for doc in list(coll.find())

Ответ 5

вы должны выбрать низкое значение batch_size, чтобы исправить проблему:

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

см. следующий ответ