Docs Menu
Docs Home
/ / /
Node.js
/ / /

Access Data From a Cursor

On this page

  • Overview
  • Cursor Paradigms
  • Asynchronous Iteration
  • Manual Iteration
  • Return an Array of All Documents
  • Stream API
  • Event API
  • Cursor Utility Methods
  • Rewind
  • Close

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. A cursor 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()

  • Collection.listSearchIndexes()

  • 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.

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() 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.

Cursors implement the AsyncIterator interface, which allows you to use cursors in for await...of loops:

const cursor = myColl.find({});
console.log("async");
for await (const doc of cursor) {
console.log(doc);
}

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 = myColl.find({});
while (await cursor.hasNext()) {
console.log(await cursor.next());
}

For use cases that require all documents matched by a query to be held in memory at the same time, use the toArray() method. Note that large numbers of matched documents can cause performance issues or failures if the operation exceeds memory constraints. Consider using the for await...of syntax to iterate through results rather than returning all documents at once.

const cursor = myColl.find({});
const allValues = await cursor.toArray();

Cursors expose the stream() method to convert them to Node Readable Streams. These streams operate in Object Mode, which passes JavaScript objects rather than Buffers or Strings through the pipeline.

const cursor = myColl.find({});
cursor.stream().on("data", doc => console.log(doc));

As Readable Streams, cursors also support the Event API's close, data, end and readable events:

const cursor = myColl.find({});
// the "data" event is fired once per document
cursor.on("data", data => console.log(data));

To reset a cursor to its initial position in the set of returned documents, use rewind().

const cursor = myColl.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);

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();

Back

Retrieve Data