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

Pymongo.errors.CursorNotFound: курсор id '...' недействителен на сервере

Я пытаюсь получить некоторые идентификаторы, которые существуют в базе данных mongo со следующим кодом:

client = MongoClient('xx.xx.xx.xx', xxx)
db = client.test_database
db = client['...']
collection = db.test_collection
collection = db["..."]


for cursor in collection.find({ "$and" : [{ "followers" : { "$gt" : 2000 } }, { "followers" : { "$lt" : 3000 } }, { "list_followers" : { "$exists" : False } }] }): 
    print cursor['screenname']
    print cursor['_id']['uid']
    id = cursor['_id']['uid']

Однако через некоторое время я получаю эту ошибку:

pymongo.errors.CursorNotFound: идентификатор курсора '...' недействителен на сервере.

Я нашел эту статью , которая ссылается на эту проблему. Тем не менее мне непонятно, какое решение взять. Можно ли использовать find().batch_size(30)? Что именно делает команда выше? Можно ли использовать все идентификаторы базы данных с помощью batch_size?

4b9b3361

Ответ 1

Вы получаете эту ошибку, потому что время ожидания курсора на сервере (после 10 минут бездействия).

Из документации по пимонго:

Курсоры в MongoDB могут тайм-аут на сервере, если они были открыты для долгое время без каких-либо операций над ними. Это может привести к возникновению исключения CursorNotFound при попытке итерируйте курсор.

Когда вы вызываете метод collection.find, он запрашивает коллекцию и возвращает курсор на документы. Чтобы получить документы, вы перебираете курсор. Когда вы перебираете курсор, драйвер фактически делает запросы серверу MongoDB для получения дополнительных данных с сервера. Количество данных, возвращаемых в каждом запросе, устанавливается методом batch_size().

Из документации:

Ограничивает количество документов, возвращаемых в одной партии. Каждая партия требует поездки в оба конца на сервер. Это можно настроить для оптимизации производительность и ограничение передачи данных.

Установка более низкого значения batch_size поможет вам при ошибках тайм-аута, но увеличит количество обращений к серверу MongoDB для получения всех документов.

Размер пакета по умолчанию:

Для большинства запросов первая партия возвращает 101 документ или достаточно документы превышают 1 мегабайт. Размер пакета не должен превышать максимальный размер документа BSON (16 МБ).

Универсального "правильного" размера партии не существует. Вы должны проверить с различными значениями и посмотреть, какое значение подходит для вашего варианта использования, то есть сколько документов вы можете обработать в 10-минутном окне.

В крайнем случае вы установите no_cursor_timeout=True. Но вы должны быть уверены, что курсор будет закрыт после завершения обработки данных.

Пример:

cursor = collection.find({"x": 1}, no_cursor_timeout=True)
for doc in cursor:
    # do something with doc
cursor.close()

Ответ 2

Вы можете настроить курсор на отсутствие тайм-аута, используя no_cursor_timeout=True, например:

cursor=db.images.find({}, {'id':1, 'image_path':1, '_id':0}, no_cursor_timeout=True)
for i in cursor:
    # .....
    # .....
cursor.close() # use this or cursor keeps waiting so ur resources are used up

Ранее это упоминалось как timeout, который был заменен согласно документам. Для получения дополнительной информации о том, какие методы поддерживают no_cursor_timeout , см. результаты этого поиска в pymongo docs.

Ответ 3

Вы использовали курсор больше времени (около 10 минут), поэтому курсор больше не существует.

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

(например, с помощью Pymongo)

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

или

установите тайм-аут на значение false col.find(timeout=False) и не забудьте закрыть курсор в конце.