Overview
En esta guía, puede aprender cómo acceder a los datos de un cursor utilizando la biblioteca PHP MongoDB.
Un cursor es un mecanismo que devuelve los resultados de una operación de lectura en lotes iterables. Los cursores reducen tanto el consumo de memoria como el número de solicitudes al servidor al mantener solo un subconjunto de documentos en cualquier momento, en lugar de devolver todos los documentos a la vez.
Siempre que la biblioteca PHP de MongoDB realiza una operación de lectura mediante el uso de MongoDB\Collection::find()
método, devuelve los documentos coincidentes en una instancia MongoDB\Driver\Cursor. La clase Cursor implementa la función de PHP. IteradorInterfaz que proporciona mayor control sobre la iteración y mayor compatibilidad con funciones PHP que trabajan con iterables. Los cursores de MongoDB solo admiten la iteración hacia adelante, por lo que no se puede rebobinar un cursor ni usar un foreach bucle varias veces.
Datos de muestra
Los ejemplos de esta guía utilizan la restaurants colección sample_restaurants de la base de datos de los conjuntos de datos de ejemplo de Atlas. Para acceder a esta colección desde su aplicación PHP, cree una MongoDB\Client instancia de que se conecte a un clúster de Atlas y asigne el siguiente valor a su $collection variable:
$collection = $client->sample_restaurants->restaurants;
Para aprender cómo crear una implementación gratuita de MongoDB y cargar los conjuntos de datos de muestra, consulte la guía de introducción a MongoDB.
Acceder al contenido del cursor de forma iterativa
La clase MongoDB\Driver\Cursor implementa la interfaz Iterator, por lo que puede utilizar un bucle foreach para iterar a través de su contenido.
El siguiente ejemplo utiliza el método MongoDB\Collection::find() para recuperar todos los documentos cuyo valor del campo name es 'Dunkin' Donuts'. A continuación, imprime cada documento desde el cursor devuelto por el método find():
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL; }
{"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40379573"} {"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40363098"} {"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40395071"} ...
Recuperar documentos individualmente
Para recuperar un documento individual de un cursor, llame al método current() en una instancia MongoDB\Driver\Cursor. Este método devuelve el documento al que apunta inicialmente el cursor. Puede continuar avanzando el cursor llamando al método next(), que le indica que apunte al siguiente documento recuperado.
El siguiente ejemplo busca todos los documentos cuyo valor del campo name sea 'Dunkin' Donuts'. A continuación, imprime el primer documento recuperado llamando al método current() en un cursor:
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $cursor->rewind(); echo json_encode($cursor->current());
{"_id":{"$oid":"..."},..."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, convierta el cursor en una matriz utilizando cualquiera de los siguientes métodos:
MongoDB\Driver\Cursor::toArray(): llamada a un
MongoDB\Driver\Cursorobjetoiterator_to_array(): Pasa un
MongoDB\Driver\Cursorobjeto como parámetro
El siguiente ejemplo llama al método toArray() en un cursor para almacenar sus resultados en una matriz:
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $resultArray = $cursor->toArray();
Cursores con seguimiento
Si desea que un cursor permanezca abierto después de que su cliente lea su contenido inicial, puede usar un cursor adaptable. Recomendamos usar cursores adaptables para consultar colecciones limitadas.
No puedes usar un bucle foreach para iterar un cursor con seguimiento, ya que el bucle termina después de leer el conjunto de resultados inicial del cursor. Si utilizas un segundo bucle foreach para seguir iterando el cursor con seguimiento, la librería de PHP intentará rebobinar el cursor y luego generará un error. En vez de eso, se deben usar los métodos de la interfaz Iterador para recuperar resultados de un cursor con seguimiento.
Para crear un cursor adaptable, establezca la opción cursorType en MongoDB\Operation\Find::TAILABLE en un array. Luego, pase el array como parámetro de opciones al método MongoDB\Collection::find().
Ejemplo de cursor adaptable
Esta sección proporciona los siguientes scripts de muestra, que puede ejecutar simultáneamente:
Un script de productor que crea una colección limitada e inserta documentos en ella
Un script de consumidor que crea un cursor adaptable para leer documentos de la colección limitada
Crear y rellenar una colección
El siguiente ejemplo crea una colección limitada llamada vegetables y espera 5 segundos antes de insertar un documento adicional en la colección:
$db = $client->db; $db->createCollection( 'vegetables', ['capped' => true, 'size' => 1024 * 1024], ); $vegetables = [ ['name' => 'cauliflower', 'createdAt' => new MongoDB\BSON\UTCDateTime()], ['name' => 'zucchini', 'createdAt' => new MongoDB\BSON\UTCDateTime()], ]; $collection = $db->vegetables; $result = $collection->insertMany($vegetables); sleep(5); $collection->insertOne(['name' => 'carrot', 'createdAt' => new MongoDB\BSON\UTCDateTime()]);
Crear un cursor adaptable
Mientras se ejecuta el ejemplo de código anterior, utilice el siguiente código para crear un cursor adaptable y recuperar todos los documentos de la vegetables colección:
$cursor = $collection->find([], ['cursorType' => MongoDB\Operation\Find::TAILABLE]); $cursor->rewind(); $docsFound = 0; while ($docsFound < 3) { if ($cursor->valid()) { $doc = $cursor->current(); echo json_encode($doc), PHP_EOL; $docsFound++; } $cursor->next(); }
{"_id":{"$oid":"..."},"name":"cauliflower","createdAt":{"$date":{"$numberLong":"..."}}} {"_id":{"$oid":"..."},"name":"zucchini","createdAt":{"$date":{"$numberLong":"..."}}} {"_id":{"$oid":"..."},"name":"carrot","createdAt":{"$date":{"$numberLong":"..."}}}
Este código imprime los dos documentos iniciales de la colección, pero el bucle while no termina hasta recibir un tercer documento. El método next() garantiza que el código espere los resultados adicionales del cursor.
Tip
Para obtener más información sobre los cursores adaptables, consulte Cursores adaptables en el manual de MongoDB Server.
Información Adicional
Para obtener más información sobre las operaciones de lectura, consulte la Guíade recuperación de datos.
Para obtener más información sobre cursores, véase las siguientes páginas en la documentación de la API de extensión:
Documentación de la API
Para obtener más información sobre el find() método, consulte la documentación de la API MongoDB\Collection::find() para.