example - python mongodb aggregation
mongodb cursor id no es un error vĂ¡lido (5)
Estoy tratando de iterar a través de este ciclo:
for doc in coll.find()
Recibo el siguiente error en el registro número 100,000 más.
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
¿Qué significa este error?
Configurar timeout=False
es una muy mala práctica. Una mejor forma de deshacerse de la excepción de tiempo de espera id de cursor es calcular cuántos documentos puede procesar su bucle en 10 minutos y obtener un tamaño de lote conservador. De esta manera, el cliente MongoDB (en este caso, PyMongo) tendrá que consultar el servidor de vez en cuando cada vez que se agotaron los documentos en el lote anterior. Esto mantendrá el cursor activo en el servidor, y aún estará cubierto por la protección de tiempo de espera de 10 minutos.
Aquí se explica cómo configura el tamaño del lote para un cursor:
for doc in coll.find().batch_size(30):
do_time_consuming_things()
Tal vez el cursor agotó el tiempo de espera en el servidor. Para ver si este es el problema, intente establecer timeout = False`:
for doc in coll.find(timeout=False)
Consulte http://api.mongodb.org/python/1.6/api/pymongo/collection.html#pymongo.collection.Collection.find
Si fue un problema de tiempo de espera, una posible solución es establecer el batch_size
(es decir, otras respuestas).
También puede forzar la evaluación utilizando:
for doc in list(coll.find())
debe elegir un valor bajo de batch_size para solucionar el problema:
col.find({}).batch_size(10)
mira la siguiente answer
- Configurar el
timeout=False
es peligroso y nunca debe usarse, porque la conexión al cursor puede permanecer abierta por tiempo ilimitado, lo que afectará el rendimiento del sistema. Los documentos hacen referencia específicamente a la necesidad de cerrar manualmente el cursor. - Establecer el
batch_size
en un pequeño número funcionará, pero crea un gran problema de latencia, porque necesitamos acceder al DB más a menudo de lo necesario.
Por ejemplo:
Los documentos de 5M con un lote pequeño demorarán horas para recuperar los mismos datos que un batch_size predeterminado devuelve en varios minutos.
En mi solución, es obligatorio usar ordenar en el cursor:
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