Overview
En esta guía, puede aprender cómo acceder a los datos de un cursor con PyMongo.
Un cursor es un mecanismo que devuelve los resultados de una operación de lectura en lotes iterables. Dado que un cursor solo contiene un subconjunto de documentos en un momento dado, reduce el consumo de memoria y el uso del ancho de banda de la red.
Siempre que PyMongo realiza una operación de lectura que devuelve varios documentos, automáticamente devuelve esos documentos en un cursor.
Datos de muestra
Los ejemplos de esta guía utilizan el sample_restaurants.restaurants colección de la Conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Tutorial paraempezar a usar PyMongo.
Acceder al contenido del cursor de forma iterativa
Para iterar sobre el contenido de un cursor, utilice un bucle for, como se muestra en el siguiente ejemplo. Seleccione el Synchronous o pestaña Asynchronous para ver el código correspondiente:
results = collection.find() for document in results: print(document)
results = collection.find() async for document in results: print(document)
Recuperar documentos individualmente
Recupere documentos de un cursor individualmente llamando al método next().
El siguiente ejemplo encuentra todos los documentos en una colección con un name valor de "Dunkin' Donuts". Luego imprime el primer documento en el cursor llamando al método next(). Seleccione la pestaña Synchronous o Asynchronous para ver el código correspondiente:
results = collection.find({ "name": "Dunkin' Donuts" }) print(results.next())
{'_id': ObjectId('...'), 'address': { ... }, 'borough': 'Bronx', 'cuisine': 'Donuts', 'grades': [...], 'name': "Dunkin' Donuts", 'restaurant_id': '40379573'}
results = collection.find({ "name": "Dunkin' Donuts" }) print(await results.next())
{'_id': ObjectId('...'), 'address': { ... }, 'borough': 'Bronx', 'cuisine': 'Donuts', 'grades': [...], 'name': "Dunkin' Donuts", 'restaurant_id': '40379573'}
Recuperar todos los documentos
Advertencia
Si la cantidad y el tamaño de los documentos devueltos por su consulta exceden la memoria disponible de la aplicación, el programa se bloqueará. Si espera un conjunto de resultados grande, acceda al cursor iterativamente.
Para recuperar todos los documentos de un cursor, conviértalo en un list, como se muestra en el siguiente ejemplo. Seleccione la pestaña Synchronous o Asynchronous para ver el código correspondiente:
results = collection.find({ "name": "Dunkin' Donuts" }) all_results = list(results) for document in all_results: print(document)
results = collection.find({ "name": "Dunkin' Donuts" }) all_results = await to_list(results) for document in all_results: print(document)
Cerrar un cursor
De forma predeterminada, MongoDB cierra un cursor cuando el cliente ha agotado todos los resultados. Para cerrar un cursor explícitamente, llame al método close() como se muestra en el siguiente ejemplo. Seleccione la pestaña Synchronous o Asynchronous para ver el código correspondiente:
results = collection.find() ... results.close()
results = collection.find() ... await results.close()
También puede instanciar un cursor en una instrucción with, como se muestra en el siguiente ejemplo. PyMongo cierra automáticamente el cursor al finalizar el bloque.
with collection.find() as cursor: for document in cursor: print(document)
Cursores con seguimiento
Al consultar una colección limitada, puede usar un cursor adaptable que permanece abierto después de que el cliente agote los resultados de un cursor. Para crear un cursor adaptable con una colección limitada, especifique CursorType.TAILABLE_AWAIT en la cursor_type opción de un find() método.
El siguiente ejemplo utiliza un cursor adaptable para seguir el registro de operaciones de un miembro del conjunto de réplicas. Seleccione la pestaña Synchronous o Asynchronous para ver el código correspondiente:
oplog = client.local.oplog.rs first = oplog.find().sort('$natural', pymongo.ASCENDING).limit(-1).next() print(first) ts = first['ts'] while True: cursor = oplog.find({'ts': {'$gt': ts}}, cursor_type=pymongo.CursorType.TAILABLE_AWAIT) while cursor.alive: for doc in cursor: ts = doc['ts'] print(doc) # You end up here if the find() method returns no documents, or if # no new documents are added to the collection for more than 1 second. time.sleep(1)
oplog = client.local.oplog.rs first = await oplog.find().sort('$natural', pymongo.ASCENDING).limit(-1).next() print(first) ts = first['ts'] while True: cursor = oplog.find({'ts': {'$gt': ts}}, cursor_type=pymongo.CursorType.TAILABLE_AWAIT) while cursor.alive: async for doc in cursor: ts = doc['ts'] print(doc) # You end up here if the find() method returns no documents, or if # no new documents are added to the collection for more than 1 second. await asyncio.sleep(1)
Para obtener más información sobre los cursores adaptables, consulte la guía Cursores adaptables en el manual del servidor MongoDB.
Solución de problemas
El objeto 'Cursor' no tiene el atributo '_Cursor__killed'
PyMongo v3.8 o anterior genera un TypeError y un AttributeError si se proporcionan argumentos no válidos al constructor Cursor. El AttributeError es irrelevante, pero el TypeError contiene información de depuración, como se muestra en el siguiente ejemplo:
Exception ignored in: <function Cursor.__del__ at 0x1048129d8> ... AttributeError: 'Cursor' object has no attribute '_Cursor__killed' ... TypeError: __init__() got an unexpected keyword argument '<argument>'
Para solucionar esto, asegúrese de proporcionar los argumentos de palabras clave correctos. También puede actualizar a PyMongo v3.9 o posterior, lo que elimina el error irrelevante.
"CursorNotFound:el ID del cursor no es válido en el servidor"
Los cursores en MongoDB pueden agotar el tiempo de espera en el servidor si han estado abiertos durante mucho tiempo sin que se les haya realizado ninguna operación. Esto puede generar una excepción CursorNotFound al intentar iterar sobre el cursor.