Overview
In this guide, you can learn how to access data from a cursor by using the MongoDB PHP Library.
A cursor is a mechanism that returns the results of a read operation in iterable batches. Cursors reduce both memory consumption and the number of server requests by holding only a subset of documents at any given time, rather than returning all documents at once.
Whenever the MongoDB PHP Library performs a read operation by using the MongoDB\Collection::find()
method, it returns the matching documents in a MongoDB\Driver\Cursor
instance.
The Cursor
class implements PHP's Iterator
interface, which provides more control over iteration and greater compatibility
with PHP functions that work with iterables.
MongoDB cursors support only forward iteration, so you cannot rewind a cursor
or use a foreach
loop multiple times.
Sample Data
The examples in this guide use the restaurants
collection in the sample_restaurants
database from the Atlas sample datasets. To access this collection
from your PHP application, instantiate a MongoDB\Client
that connects to an Atlas cluster
and assign the following value to your $collection
variable:
$collection = $client->sample_restaurants->restaurants;
To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see the Get Started with Atlas guide.
Access Cursor Contents Iteratively
The MongoDB\Driver\Cursor
class implements the Iterator
interface, so you
can use a foreach
loop to iterate through its contents.
The following example uses the MongoDB\Collection::find()
method to retrieve all documents
in which the name
field value is 'Dunkin' Donuts'
. It then prints each document from the
cursor returned by the find()
method:
$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"} ...
Retrieve Documents Individually
To retrieve an individual document from a cursor, call the current()
method on
a MongoDB\Driver\Cursor
instance. This method returns the document that the cursor
initially points to. You can continue to advance the cursor by calling the next()
method, which instructs the cursor to point to the next retrieved document.
The following example finds all documents in which the name
field value is
'Dunkin' Donuts'
. Then, it prints the first retrieved document by calling the
current()
method on a cursor:
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $cursor->rewind(); echo json_encode($cursor->current());
{"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40379573"}
Retrieve All Documents
Warning
If the number and size of documents returned by your query exceeds available application memory, your program will crash. If you expect a large result set, access your cursor iteratively.
To retrieve all documents from a cursor, convert the cursor into an array by using either of the following methods:
MongoDB\Driver\Cursor::toArray(): Call on a
MongoDB\Driver\Cursor
objectiterator_to_array(): Pass a
MongoDB\Driver\Cursor
object as a parameter
The following example calls the toArray()
method on a cursor to store its results
in an array:
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $resultArray = $cursor->toArray();
Tailable Cursors
If you want a cursor to remain open after your client reads its initial contents, you can use a tailable cursor. We recommend that you use tailable cursors to query capped collections.
You cannot use a foreach
loop to iterate a tailable cursor, since
the loop terminates after reading the cursor's initial result set. If you
use a second foreach
loop to continue iterating the tailable cursor,
the PHP library attempts to rewind the cursor and then generates an error.
Instead, you must use methods from the Iterator interface
to retrieve results from a tailable cursor.
To create a tailable cursor, set the cursorType
option to
MongoDB\Operation\Find::TAILABLE
in an array. Then, pass the array as an options
parameter to the MongoDB\Collection::find()
method.
Tailable Cursor Example
This section provides the following sample scripts, which you can run simultaneously:
A producer script that creates a capped collection and inserts documents into it
A consumer script that creates a tailable cursor to read documents from the capped collection
Create and Populate a Collection
The following example creates a capped collection called vegetables
and
waits 5
seconds before inserting an additional document into the collection:
$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()]);
Create a Tailable Cursor
While the preceding code example is running, use the following
code to create a tailable cursor and retrieve all documents in the vegetables
collection:
$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":"..."}}}
This code prints the two initial documents in the collection, but the while
loop does not terminate until receiving a third document. The next()
method ensures that the code waits for the additional cursor results.
Tip
To learn more about tailable cursors, see Tailable Cursors in the MongoDB Server manual.
Additional Information
To learn more about read operations, see the Retrieve Data guide.
To learn more about cursors, see the following pages in the extension API documentation:
API Documentation
To learn more about the find()
method, see the API documentation for
MongoDB\Collection::find()
.