Skip to content

Commit 6e0dcb6

Browse files
committed
DOCSP-41980: Cursor guide
1 parent e994533 commit 6e0dcb6

File tree

4 files changed

+244
-1
lines changed

4 files changed

+244
-1
lines changed

snooty.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ php-library = "MongoDB PHP Library"
2525
[constants]
2626
php-library = "MongoDB PHP Library"
2727
api = "https://www.mongodb.com/docs/php-library/current/reference"
28+
php-manual = "https://www.php.net/manual/en"

source/includes/read/cursor.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
require 'vendor/autoload.php';
3+
4+
$uri = getenv('MONGODB_URI') ?: throw new RuntimeException('Set the MONGODB_URI variable to your Atlas URI that connects to the sample dataset');
5+
$client = new MongoDB\Client($uri);
6+
7+
// start-db-coll
8+
$collection = $client->sample_restaurants->restaurants;
9+
// end-db-coll
10+
11+
// Iterates over and prints all documents that have a "name" value of "Dunkin' Donuts"
12+
// start-cursor-iterate
13+
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']);
14+
foreach ($cursor as $doc) {
15+
echo json_encode($doc) . PHP_EOL;
16+
}
17+
// end-cursor-iterate
18+
19+
// Retrieves and prints the first document stored in the cursor
20+
// start-cursor-first
21+
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']);
22+
echo json_encode($cursor->current());
23+
// end-cursor-first
24+
25+
// Converts the documents stored in a cursor to an array
26+
// start-cursor-array
27+
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']);
28+
$array_results = $cursor->toArray();
29+
// end-cursor-array
30+
31+
// Creates a collection with a maximum size and inserts documents representing vegetables
32+
// start-capped-coll
33+
$db = $client->db;
34+
$collection = $db->createCollection(
35+
'vegetables',
36+
['capped' => true, 'size' => 1024 * 1024]
37+
);
38+
39+
$vegetables = [
40+
['name' => 'cauliflower'],
41+
['name' => 'zucchini']
42+
];
43+
44+
$result = $collection->insertMany($vegetables);
45+
// end-capped-coll
46+
47+
// Iterates over the initial query results and continues iterating until three documents are stored in the cursor
48+
// by using a tailable cursor
49+
// start-tailable
50+
$cursor = $collection->find([], ['cursorType' => 'tailable']);
51+
52+
$docs_found = 0;
53+
while ($docs_found < 3) {
54+
foreach ($cursor as $doc) {
55+
echo json_encode($doc) . PHP_EOL;
56+
$docs_found++;
57+
}
58+
59+
// Sleeps for 100 milliseconds before trying to access more documents
60+
usleep(100000); // 100 milliseconds
61+
}
62+
// end-tailable
63+

source/read.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ Read Data from MongoDB
88
:titlesonly:
99
:maxdepth: 1
1010

11-
/read/retrieve
11+
/read/retrieve
12+
/read/cursor

source/read/cursor.txt

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
.. _php-cursors:
2+
3+
=========================
4+
Access Data From a Cursor
5+
=========================
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 1
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: read, results, oplog
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to access data from a **cursor** by using the
24+
{+php-library+}.
25+
26+
A cursor is a mechanism that returns the results of a read operation in iterable
27+
batches. Cursors reduce both memory consumption and network bandwidth usage by holding
28+
only a subset of documents at any given time rather than returning all documents at
29+
once.
30+
31+
Whenever the {+php-library+} performs a read operation by using the ``MongoDB\Collection::find()``
32+
method, it returns the matching documents in a ``MongoDB\Driver\Cursor`` instance.
33+
34+
Sample Data
35+
~~~~~~~~~~~
36+
37+
The examples in this guide use the ``restaurants`` collection in the ``sample_restaurants``
38+
database from the :atlas:`Atlas sample datasets </sample-data>`. To access this collection
39+
from your PHP application, instantiate a ``MongoDB\Client`` that connects to an Atlas cluster
40+
and assign the following value to your ``collection`` variable:
41+
42+
.. literalinclude:: /includes/read/distinct.php
43+
:language: php
44+
:dedent:
45+
:start-after: start-db-coll
46+
:end-before: end-db-coll
47+
48+
To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see the
49+
:atlas:`Get Started with Atlas </getting-started>` guide.
50+
51+
.. _php-cursors-iterate:
52+
53+
Access Cursor Contents Iteratively
54+
----------------------------------
55+
56+
To iterate over the contents of a ``MongoDB\Driver\Cursor`` instance, use a ``foreach`` loop.
57+
58+
The following example uses the ``MongoDB\Collection::find()`` method to retrieve all documents
59+
in which the ``name`` value is ``'Dunkin' Donuts'``. It then prints each document from the
60+
cursor returned by the ``find()`` method:
61+
62+
.. io-code-block::
63+
:copyable:
64+
65+
.. input:: /includes/read/cursor.php
66+
:start-after: start-cursor-iterate
67+
:end-before: end-cursor-iterate
68+
:language: php
69+
:dedent:
70+
71+
.. output::
72+
:visible: false
73+
74+
{ "_id" : { "$oid" : "..." }, ... "name" : "Dunkin' Donuts", "restaurant_id" : "40379573" }
75+
{ "_id" : { "$oid" : "..." }, ... "name" : "Dunkin' Donuts", "restaurant_id" : "40363098" }
76+
{ "_id" : { "$oid" : "..." }, ... "name" : "Dunkin' Donuts", "restaurant_id" : "40395071" }
77+
...
78+
79+
Retrieve Documents Individually
80+
-------------------------------
81+
82+
To retrieve an individual document from a cursor, call the ``current()`` method on
83+
a ``MongoDB\Driver\Cursor`` instance. This method returns the document that the cursor
84+
currently points to. You can continue to advance the cursor by calling the ``next()``
85+
method, which instructs the cursor to point to the next retrieved document.
86+
87+
The following example finds all documents in a collection that have a ``name`` value
88+
of ``'Dunkin' Donuts'``. Then, it prints the first retrieved document by calling the
89+
``current()`` method on a cursor:
90+
91+
.. io-code-block::
92+
:copyable:
93+
94+
.. input:: /includes/read/cursor.php
95+
:start-after: start-cursor-first
96+
:end-before: end-cursor-first
97+
:language: php
98+
:dedent:
99+
100+
.. output::
101+
102+
{ "_id" : { "$oid" : "..." }, ... "name" : "Dunkin' Donuts", "restaurant_id" : "40379573" }
103+
104+
Retrieve All Documents
105+
----------------------
106+
107+
.. warning::
108+
109+
If the number and size of documents returned by your query exceeds available
110+
application memory, your program will crash. If you expect a large result
111+
set, :ref:`access your cursor iteratively <php-cursors-iterate>`.
112+
113+
To retrieve all documents from a cursor, convert the cursor into an array as
114+
shown in the following example:
115+
116+
.. literalinclude:: /includes/read/cursor.php
117+
:language: php
118+
:dedent:
119+
:start-after: start-cursor-array
120+
:end-before: end-cursor-array
121+
122+
Tailable Cursors
123+
----------------
124+
125+
When querying on a :manual:`capped collection </core/capped-collections/>`, you
126+
can use a **tailable cursor** that remains open after the client exhausts the
127+
results in a cursor. To create a tailable cursor, set the ``cursorType`` option to
128+
``tailable`` in an array. Then, pass the array as an options parameter to
129+
the ``MongoDB\Collection::find()`` method.
130+
131+
For example, you can create a capped collection called ``vegetables`` that stores
132+
documents representing vegetables, as shown in the following code:
133+
134+
.. literalinclude:: /includes/read/cursor.php
135+
:language: php
136+
:dedent:
137+
:start-after: start-capped-coll
138+
:end-before: end-capped-coll
139+
140+
The following code uses a tailable cursor to retrieve all documents in the ``vegetables``
141+
collection. After the cursor is exhausted, it remains open until retrieving three documents:
142+
143+
.. io-code-block::
144+
:copyable:
145+
146+
.. input:: /includes/read/cursor.php
147+
:start-after: start-tailable
148+
:end-before: end-tailable
149+
:language: php
150+
:dedent:
151+
152+
.. output::
153+
154+
{ "_id" : { "$oid" : "..." }, "name" : "cauliflower" }
155+
{ "_id" : { "$oid" : "..." }, "name" : "zucchini" }
156+
157+
If you insert another document into the ``vegetables`` collection, the preceding code prints
158+
the new document and closes the ``while`` loop.
159+
160+
To learn more about tailable cursors, see the :manual:`Tailable Cursors guide
161+
</core/tailable-cursors/>` in the {+mdb-server+} manual.
162+
163+
Additional Information
164+
----------------------
165+
166+
To learn more about read operations, see the :ref:`php-retrieve` guide.
167+
168+
To learn more about cursors, see the following pages in the PHP manual:
169+
170+
- `MongoDB\Driver\Cursor <{+php-manual+}/class.mongodb-driver-cursor.php>`__
171+
- `MongoDB\Driver\Cursor::current() <{+php-manual+}/mongodb-driver-cursor.current.php>`__
172+
- `MongoDB\Driver\Cursor::toArray() <{+php-manual+}/mongodb-driver-cursor.toarray.php>`__
173+
174+
API Documentation
175+
~~~~~~~~~~~~~~~~~
176+
177+
To learn more about the ``find()`` method, see `MongoDB\\Collection::find()
178+
<{+api+}/method/MongoDBCollection-find/>`__ in the API documentation.

0 commit comments

Comments
 (0)