Docs Menu

Docs HomeDevelop ApplicationsMongoDB DriversNode.js

Access Data From a Cursor

On this page

  • Overview
  • Cursor Paradigms
  • For Each Functional Iteration
  • Return an Array of All Documents
  • Asynchronous Iteration
  • Manual Iteration
  • Stream API
  • Event API
  • Cursor Utility Methods
  • Count
  • 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 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.

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.

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

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

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

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

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

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

For an estimated count of the number of documents referenced by the cursor, use count():

const cursor = collection.find({});
const count = await cursor.count();

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

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();
←  Retrieve DataRetrieve Distinct Values →