Skip to content

Commit 0991759

Browse files
authored
DOCSP-41139: Cursors (mongodb#25)
1 parent 626ef2e commit 0991759

File tree

3 files changed

+245
-0
lines changed

3 files changed

+245
-0
lines changed

source/includes/read/cursors.kt

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package org.example
2+
import com.mongodb.ConnectionString
3+
import com.mongodb.CursorType
4+
import com.mongodb.MongoClientSettings
5+
import com.mongodb.client.model.Filters.eq
6+
import com.mongodb.kotlin.client.MongoClient
7+
import org.bson.codecs.pojo.annotations.BsonId
8+
import org.bson.types.ObjectId
9+
import org.bson.Document
10+
11+
// start-data-class
12+
data class Restaurant(
13+
@BsonId
14+
val id: ObjectId,
15+
val name: String
16+
)
17+
// end-data-class
18+
19+
fun main() {
20+
val uri = "<connection string URI>"
21+
22+
val settings = MongoClientSettings.builder()
23+
.applyConnectionString(ConnectionString(uri))
24+
.retryWrites(true)
25+
.build()
26+
27+
val mongoClient = MongoClient.create(settings)
28+
val database = mongoClient.getDatabase("sample_restaurants")
29+
val collection = database.getCollection<Restaurant>("restaurants")
30+
31+
// start-cursor-iterate
32+
val results = collection.find()
33+
34+
results.forEach { result ->
35+
println(result)
36+
}
37+
// end-cursor-iterate
38+
39+
// start-cursor-iterate-alternative
40+
val results = collection.find()
41+
42+
results.cursor().use { cursor ->
43+
while (cursor.hasNext()) {
44+
println(resultCursor.next())
45+
}
46+
}
47+
// end-cursor-iterate-alternative
48+
49+
// start-cursor-next
50+
val results = collection
51+
.find<Restaurant>(eq(Restaurant::name.name, "Dunkin' Donuts"))
52+
53+
results.cursor().use { cursor ->
54+
println(if (cursor.hasNext()) cursor.next()
55+
else "No document matches the filter")
56+
}
57+
// end-cursor-next
58+
59+
// start-cursor-list
60+
val results = collection.find<Restaurant>(eq(Restaurant::name.name, "Dunkin' Donuts"))
61+
val resultsList = results.toList()
62+
63+
for (result in resultsList) {
64+
println(result)
65+
}
66+
// end-cursor-list
67+
68+
// start-tailable-cursor
69+
val results = collection.find<Document>().cursorType(CursorType.TailableAwait)
70+
// end-tailable-cursor
71+
}

source/read.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Read Data from MongoDB
2828
/read/specify-documents-to-return
2929
/read/count
3030
/read/distinct
31+
/read/cursors
3132
/read/change-streams
3233

3334
Overview

source/read/cursors.txt

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
.. _kotlin-sync-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** with the
24+
{+driver-short+}.
25+
26+
A cursor is a mechanism that returns the results of a read operation in iterable
27+
batches. Because a cursor holds only a subset of documents at any given time,
28+
cursors reduce both memory consumption and the number of requests the driver sends to
29+
the server.
30+
31+
Whenever the {+driver-short+} performs a read operation that returns multiple
32+
documents, it automatically returns those documents in a cursor.
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 learn how to create a
39+
free MongoDB Atlas cluster and load the sample datasets, see the
40+
:atlas:`Get Started with Atlas </getting-started>` guide.
41+
42+
The following {+language+} data class models the documents in this collection:
43+
44+
.. literalinclude:: /includes/read/cursors.kt
45+
:start-after: start-data-class
46+
:end-before: end-data-class
47+
:language: kotlin
48+
:copyable:
49+
50+
.. _kotlin-sync-cursors-iterate:
51+
52+
Access Cursor Contents Iteratively
53+
----------------------------------
54+
55+
To iterate over the contents of a cursor, use the ``forEach()`` method, as shown in the
56+
following example:
57+
58+
.. literalinclude:: /includes/read/cursors.kt
59+
:start-after: start-cursor-iterate
60+
:end-before: end-cursor-iterate
61+
:language: kotlin
62+
:copyable:
63+
:dedent:
64+
65+
Alternatively, use the ``use()`` method to implement a loop on the cursor:
66+
67+
.. literalinclude:: /includes/read/cursors.kt
68+
:start-after: start-cursor-iterate-alternative
69+
:end-before: end-cursor-iterate-alternative
70+
:language: kotlin
71+
:copyable:
72+
:dedent:
73+
74+
.. note::
75+
76+
By default, MongoDB closes a cursor when the client has exhausted all the
77+
results in the cursor. The examples in this guide explicitly close cursors by using the
78+
``close()`` method.
79+
80+
Retrieve Documents Individually
81+
-------------------------------
82+
83+
Retrieve documents from a cursor individually by calling the ``next()`` method.
84+
85+
The following example finds all documents in a collection with a ``name`` value
86+
of ``"Dunkin' Donuts"``. It then prints the first document in the cursor by calling the
87+
``next()`` method.
88+
89+
.. io-code-block::
90+
:copyable:
91+
92+
.. input:: /includes/read/cursors.kt
93+
:start-after: start-cursor-next
94+
:end-before: end-cursor-next
95+
:language: kotlin
96+
:dedent:
97+
98+
.. output::
99+
:visible: false
100+
101+
Restaurant(id=5eb3d668b31de5d588f42c66, name=Dunkin' Donuts)
102+
103+
Retrieve All Documents
104+
----------------------
105+
106+
.. warning::
107+
108+
If the number and size of documents returned by your query exceeds available
109+
application memory, your program will crash. If you expect a large result
110+
set, :ref:`access your cursor iteratively <kotlin-sync-cursors-iterate>`.
111+
112+
To retrieve all documents from a cursor, convert the cursor into a ``List`` as
113+
shown in the following example:
114+
115+
.. io-code-block::
116+
:copyable:
117+
118+
.. input:: /includes/read/cursors.kt
119+
:start-after: start-cursor-list
120+
:end-before: end-cursor-list
121+
:language: kotlin
122+
:dedent:
123+
124+
.. output::
125+
:visible: false
126+
127+
Restaurant(id=5eb3d668b31de5d588f42c66, name=Dunkin' Donuts)
128+
Restaurant(id=5eb3d668b31de5d588f42ca0, name=Dunkin' Donuts)
129+
Restaurant(id=5eb3d668b31de5d588f42b08, name=Dunkin' Donuts)
130+
Restaurant(id=5eb3d668b31de5d588f42cd7, name=Dunkin' Donuts)
131+
...
132+
133+
Tailable Cursors
134+
----------------
135+
136+
When querying on a :manual:`capped collection </core/capped-collections/>`, you
137+
can use a **tailable cursor** that remains open after the client exhausts the
138+
results in a cursor. To create a tailable cursor with capped collection,
139+
specify ``CursorType.TailableAwait`` to the ``cursorType`` method of a
140+
``FindIterable`` object.
141+
142+
The following example creates a tailable cursor on a capped collection:
143+
144+
.. literalinclude:: /includes/read/cursors.kt
145+
:start-after: start-tailable-cursor
146+
:end-before: end-tailable-cursor
147+
:language: kotlin
148+
:copyable:
149+
:dedent:
150+
151+
To learn more about tailable cursors and their usage, see the :manual:`Tailable Cursors guide
152+
</core/tailable-cursors/>` in the {+mdb-server+} manual.
153+
154+
Troubleshooting
155+
---------------
156+
157+
"*CursorNotFound* cursor id not valid at server"
158+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
159+
160+
Cursors in MongoDB can timeout on the server if they've been open for
161+
a long time without any operations being performed on them. This can
162+
lead to a ``CursorNotFound`` exception when you try to iterate through the cursor.
163+
164+
API Documentation
165+
-----------------
166+
167+
To learn more about any of the methods or types discussed in this
168+
guide, see the following API documentation:
169+
170+
- `find() <{+api+}/mongodb-driver-kotlin-sync/com.mongodb.kotlin.client/-mongo-collection/find.html>`__
171+
- `FindIterable <{+api+}/mongodb-driver-kotlin-sync/com.mongodb.kotlin.client/-find-iterable/index.html>`__
172+
- `MongoCursor <{+api+}/mongodb-driver-kotlin-sync/com.mongodb.kotlin.client/-mongo-cursor/index.html>`__
173+
- `CursorType <{+core-api+}/com/mongodb/CursorType.html>`__

0 commit comments

Comments
 (0)