Access Data From a Cursor
On this page
Overview
In this guide, you can learn how to access data from a cursor with the Kotlin Sync driver.
A cursor is a mechanism that returns the results of a read operation in iterable batches. Because a cursor holds only a subset of documents at any given time, cursors reduce both memory consumption and the number of requests the driver sends to the server.
Whenever the Kotlin Sync driver performs a read operation that returns multiple documents, it automatically returns those documents in a cursor.
Sample Data
The examples in this guide use the restaurants
collection in the sample_restaurants
database from the Atlas sample datasets. To learn how to create a
free MongoDB Atlas cluster and load the sample datasets, see the
Get Started with Atlas guide.
The following Kotlin data class models the documents in this collection:
data class Restaurant( val id: ObjectId, val name: String )
Access Cursor Contents Iteratively
To iterate over the contents of a cursor, use the forEach()
method, as shown in the
following example:
val results = collection.find() results.forEach { result -> println(result) }
Alternatively, use the use()
method to implement a loop on the cursor:
val results = collection.find() results.cursor().use { cursor -> while (cursor.hasNext()) { println(resultCursor.next()) } }
Note
By default, MongoDB closes a cursor when the client has exhausted all the
results in the cursor. The examples in this guide explicitly close cursors by using the
close()
method.
Retrieve Documents Individually
Retrieve documents from a cursor individually by calling the next()
method.
The following example finds all documents in a collection with a name
value
of "Dunkin' Donuts"
. It then prints the first document in the cursor by calling the
next()
method.
val results = collection .find<Restaurant>(eq(Restaurant::name.name, "Dunkin' Donuts")) results.cursor().use { cursor -> println(if (cursor.hasNext()) cursor.next() else "No document matches the filter") }
Restaurant(id=5eb3d668b31de5d588f42c66, name=Dunkin' Donuts)
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 a List
as
shown in the following example:
val results = collection.find<Restaurant>(eq(Restaurant::name.name, "Dunkin' Donuts")) val resultsList = results.toList() for (result in resultsList) { println(result) }
Restaurant(id=5eb3d668b31de5d588f42c66, name=Dunkin' Donuts) Restaurant(id=5eb3d668b31de5d588f42ca0, name=Dunkin' Donuts) Restaurant(id=5eb3d668b31de5d588f42b08, name=Dunkin' Donuts) Restaurant(id=5eb3d668b31de5d588f42cd7, name=Dunkin' Donuts) ...
Tailable Cursors
When querying on a capped collection, you
can use a tailable cursor that remains open after the client exhausts the
results in a cursor. To create a tailable cursor with capped collection,
specify CursorType.TailableAwait
to the cursorType
method of a
FindIterable
object.
The following example creates a tailable cursor on a capped collection:
val results = collection.find<Document>().cursorType(CursorType.TailableAwait)
To learn more about tailable cursors and their usage, see the Tailable Cursors guide in the MongoDB Server manual.
Troubleshooting
"CursorNotFound cursor id not valid at server"
Cursors in MongoDB can timeout on the server if they've been open for
a long time without any operations being performed on them. This can
lead to a CursorNotFound
exception when you try to iterate through the cursor.
API Documentation
To learn more about any of the methods or types discussed in this guide, see the following API documentation: