Docs Home → Develop Applications → MongoDB Drivers → Node.js
Access Data From a Cursor
On this page
Overview
Read operations that return multiple documents do not immediately return all values matching the query. Because a query can potentially match very large sets of documents, these operations rely upon an object called a cursor that fetches documents in batches to reduce both memory consumption and network bandwidth usage. Cursors are highly configurable and offer multiple interaction paradigms for different use cases.
The following functions directly return cursors:
Collection.find()
Collection.aggregate()
Collection.listIndexes()
Db.aggregate()
Db.listCollections()
Other methods such as Collection.findOne() and Collection.watch() use cursors internally, and return the results of the operations instead of a cursor.
Cursor Paradigms
You can work with cursors using a number of cursor paradigms. Most cursor paradigms allow you to access query results one document at a time, abstracting away network and caching logic. However, since use cases differ, other paradigms offer different access patterns, like pulling all matching documents into a collection in process memory.
Warning
Do not combine different cursor paradigms on a single cursor.
Operations such as hasNext()
, forEach()
, and toArray()
each predictably modify the original cursor. If you mix these calls
on a single cursor, you may receive unexpected results.
Warning
Because asynchronous calls directly modify the cursor, executing asynchronous calls on a single cursor simultaneously can also cause undefined behavior. Always wait for the previous asynchronous operation to complete before running another.
Note
When you reach the last result through iteration or through an at-once fetch, the cursor is exhausted which means it ceases to respond to methods that access the results.
For Each Functional Iteration
You can pass a function to the forEach() method of any cursor to iterate through results in a functional style:
const cursor = collection.find({}); await cursor.forEach(doc => console.log(doc));
Return an Array of All Documents
For use cases that require all documents matched by a query to be held in memory at the same time, use toArray(). Note that large numbers of matched documents can cause performance issues or failures if the operation exceeds memory constraints. Consider using forEach() to iterate through results unless you want to return all documents at once.
const cursor = collection.find({}); const allValues = await cursor.toArray();
Asynchronous Iteration
Cursors implement the AsyncIterator interface, which
allows you to use cursors in for
...``await`` loops:
const cursor = collection.find({}); console.log("async"); for await (const doc of cursor) { console.log(doc); }
Manual Iteration
You can use the hasNext() method to check if a cursor can provide additional data, and then use the next() method to retrieve the subsequent element of the cursor:
const cursor = collection.find({}); while (await cursor.hasNext()) { console.log(await cursor.next()); }
Stream API
All cursors are Node Readable Streams that operate in Object Mode which passes JavaScript objects rather than Buffers or Strings through the pipeline. Cursors work with most Node stream APIs:
const cursor = collection.find({}); cursor.pipe( new stream.Writable({ objectMode: true, write: function(doc, _, callback) { console.log(doc); callback(); }, }), );
Event API
As Readable Streams, cursors also support the Event API's
close
, data
, end
and readable
events:
const cursor = collection.find({}); // the "data" event is fired once per document cursor.on("data", data => console.log(data));
Cursor Utility Methods
Count
For an estimated count of the number of documents referenced by the cursor, use count():
const cursor = collection.find({}); const count = await cursor.count();
Rewind
To reset a cursor to its initial position in the set of returned documents, use rewind().
const cursor = collection.find({}); const firstResult = await cursor.toArray(); console.log("First count: " + firstResult.length); await cursor.rewind(); const secondResult = await cursor.toArray(); console.log("Second count: " + secondResult.length);
Close
Cursors consume memory and network resources both in the client application and in the connected instance of MongoDB. Use close() to free up a cursor's resources in both the client application and the MongoDB server:
await cursor.close();