Internal Should not be instantiated directly.
Optional Internal _currentReadonly Internal _internalOptional Readonly Internal _mappingProtected Internal _stateReadonly Internal _timeoutThis temporary error-ing property exists for migration convenience, and will be removed in a future version.
.bufferedCount() has been renamed to simply be .buffered().Sets whether vector similarity scores should be included in the cursor's results.
✏️Note: This is only applicable when using vector search, and is ignored otherwise.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with the new similarity settings.
Optional includeSimilarity: booleanWhether similarity scores should be included.
const cursor = collection.find({ name: 'John' })
.sort({ $vector: new DataAPIVector([...]) })
.includeSimilarity();
// The cursor will return the similarity scores for each record
const closest = await cursor.next();
closest.$similarity; // number
A new cursor with the new similarity setting.
Map all records using the provided mapping function. Previous mapping functions will be composed with the new mapping function (new ∘ old).
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with the new mapping function applied.
⚠️Warning: You may NOT provide a projection after a mapping is already provided, to prevent potential type de-sync errors.
const cursor = collection.find({ name: 'John' })
.map(doc => doc.name);
.map(name => name.toLowerCase());
// T is `string` because the mapping function returns a string
const name = await cursor.next();
name === 'john'; // true
A new cursor with the new mapping set.
Sets the projection for the cursor, overwriting any previous projection.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new projection.
🚨Important: To properly type this method, you should provide a type argument to specify the shape of the projected records.
⚠️Warning: You may NOT provide a projection after a mapping is already provided, to prevent potential type de-sync errors.
Specifies which fields should be included/excluded in the returned records.
const cursor = collection.find({ name: 'John' });
// T is `Partial<Schema>` because the type is not specified
const rawProjected = cursor.project({ id: 0, name: 1 });
// T is `{ name: string }`
const projected = cursor.project<{ name: string }>({ id: 0, name: 1 });
// You can also chain instead of using intermediate variables
const fluentlyProjected = collection
.find({ name: 'John' })
.project<{ name: string }>({ id: 0, name: 1 })
.map(doc => doc.name);
A new cursor with the new projection set.
This temporary error-ing property exists for migration convenience, and will be removed in a future version.
.readBufferedDocuments() has been renamed to be .consumeBuffer().const coll = db.collection(...);
const cursor = coll.find({});
cursor.dataSource === coll; // true
Gets the current status of the cursor.
See CursorState for more information on the possible states, and how they may be transitioned between each other.
const cursor = collection.find({});
console.log(cursor.state); // 'idle'
await cursor.next();
console.log(cursor.state); // 'started'
cursor.close();
console.log(cursor.state); // 'closed'
CursorState
An async iterator that lazily iterates over all records in the cursor.
⚠️Warning: There'll only be partial results if the cursor has been consumed prior. You may use AbstractCursor.rewind to reset the cursor.
breaks, iteration will stop earlyconst cursor = collection.find({ age: { $gt: 30 } });
// Iterate over all matching records
for await (const doc of cursor) {
console.log(doc);
if (doc.name === 'John') {
break; // Stop iteration early
}
}
// Cursor is now closed
console.log(cursor.state); // 'closed'
Protected _fetchProtected _tmGets the number of raw records in the buffer.
Unless the cursor was closed before the buffer was completely read, the total number of records retrieved from the
server is equal to (consumed() + buffered()).
The number of raw records currently in the buffer.
const cursor = collection.find({});
console.log(cursor.buffered()); // 0
await cursor.next(); // Fetches a page of results
console.log(cursor.buffered()); // Number of records in buffer
AbstractCursor.consumed
Creates a new cursor with the exact same configuration as the current cursor.
The new cursor will be in the 'idle' state, regardless of the state of the current cursor, and will start its own iteration from the beginning, sending new queries to the server, even if the resultant data was already fetched by the original cursor.
A new cursor with the same configuration as the current cursor.
const cursor = collection.find({ age: { $gt: 30 } }).sort({ name: 1 });
// Clone the cursor before use
const clone1 = cursor.clone();
const clone2 = cursor.clone();
// Each cursor operates independently
const firstResult = await clone1.toArray();
const firstTwoRecords = await clone2.next();
// Original cursor is still usable
for await (const doc of cursor) {
console.log(doc);
}
Cloning a cursor is different from rewinding it. Cloning creates an independent new cursor with the same configuration as the original, while rewinding resets the current cursor to its initial state.
See FindCursor.rewind for more information on rewinding.
FindCursor.rewind
Closes the cursor. The cursor will be unusable after this method is called, or until AbstractCursor.rewind is called.
const cursor = collection.find({});
// Use the cursor
const doc = await cursor.next();
// Close the cursor when done
cursor.close();
// Attempting to use a closed cursor
await cursor.next(); // Throws CursorError
AbstractCursor.rewind - To reset a closed cursor to make it usable again
Consumes up to max records from the buffer, or all records if max is not provided.
⚠️Warning: This actually consumes the buffer; it doesn't just peek at it.
🚨Important: The records returned from this method are not affected by
cursor.map().
Optional max: numberThe optional max number of records to read from the buffer.
The records read from the buffer.
const cursor = collection.find({});
await cursor.next(); // Populates the buffer
// Consume up to 5 records from the buffer
const records = cursor.consumeBuffer(5);
console.log(records.length); // Number of records consumed (up to 5)
// Consume all remaining records
const remaining = cursor.consumeBuffer();
Gets the number of records that have been read by the user from the cursor.
Unless the cursor was closed before the buffer was completely read, the total number of records retrieved from the
server is equal to (consumed() + buffered()).
The number of records that have been read from the cursor.
const cursor = collection.find({});
console.log(cursor.consumed()); // 0
await cursor.next();
console.log(cursor.consumed()); // 1
AbstractCursor.buffered
Fetches the next complete page of results from the server and returns it directly.
This method provides direct access to the underlying pagination mechanism, allowing you to handle pagination manually instead of relying solely on the cursor's iteration methods.
This is primarily useful when pagination is driven by a separate process (e.g. in client/server architectures where the client maintains the page state).
🚨Important: This method will throw an error if the cursor's buffer is not empty or if the cursor is closed. This prevents misalignment between manual pagination and other cursor methods.
✏️Note: For most use cases, the standard cursor iteration methods (like
next(),hasNext(), or usingfor await...of) are more convenient than manual pagination.
A page object containing the results, the next page state, and optionally the sort vector.
// Server-side code
async function getPageOfResults(pageState?: string) {
const cursor = collection.find({ status: 'active' })
.initialPageState(pageState);
const page = await cursor.fetchNextPage();
return {
nextPageState: page.nextPageState,
results: page.result,
};
}
// Client can then use the nextPageState to fetch subsequent pages
The method returns an object with the following properties:
result: An array of documents matching the query, with all mappings applied.nextPageState: A string that can be used to fetch the next page, or null if there are no more results.sortVector: The vector used for sorting when vector search is used (only if includeSortVector is set to true).FindCursor.initialPageState
Sets the filter for the cursor, overwriting any previous filter.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new
filter.
A filter to select which records to return.
A new cursor with the new filter set.
await collection.insertOne({ name: 'John', ... });
const cursor = collection.find({})
.filter({ name: 'John' });
// The cursor will only return records with the name 'John'
const john = await cursor.next();
john.name === 'John'; // true
Iterates over all records in the cursor, calling the provided consumer for each record.
⚠️Warning: There'll only be partial results if the cursor has been consumed prior. You may use AbstractCursor.rewind to reset the cursor.
✏️Note: If you get an IDE error "Promise returned from forEach argument is ignored", you may simply ignore it. It is a known WebStorm bug.
false or Promise<false>, iteration will stop earlyThe consumer to call for each record. Return false to stop iteration.
A promise that resolves when iteration is complete.
const cursor = collection.find({ age: { $gt: 30 } });
// Process all records
await cursor.forEach((doc) => {
console.log(doc);
});
// Process records until a condition is met
await cursor.forEach(async (doc) => {
if (await isSpecial(doc)) {
return false;
}
});
Retrieves the vector used to perform the vector search, if applicable.
🚨Important: This will only return a non-null value if FindCursor.includeSortVector has been set.
The sort vector used to perform the vector search, or null if not applicable.
// Using $vector
const vector = new DataAPIVector([0.1, 0.2, 0.3]);
const cursor = collection.find({})
.sort({ $vector: vector })
.includeSortVector();
const sortVector = await cursor.getSortVector();
// Returns the same vector used in the sort
// Using $vectorize
const cursor = collection.find({})
.sort({ $vectorize: 'some text' })
.includeSortVector();
const sortVector = await cursor.getSortVector();
// Returns the vector generated from the text
This method will:
null if includeSortVector was not set to truesort: { $vector } was usedsort: { $vectorize } was usednull if vector search was not usedIf this method is called before the cursor has been executed, it will make an API request to fetch the sort vector and also populate the cursor's buffer.
If the cursor has already been executed, the sort vector will have already been cached, so no additional request will be made.
Tests if there is a next record in the cursor.
falseWhether or not there is a next record.
const cursor = collection.find({ name: 'John' });
// Check if there are any records
if (await cursor.hasNext()) {
const john = await cursor.next();
console.log(john);
}
// Use in a loop
while (await cursor.hasNext()) {
const record = await cursor.next();
console.log(record);
}
Sets whether the sort vector should be fetched on the very first API call.
This is a requirement to use FindCursor.getSortVector, which will unconditionally return null if this is not set to true.
true.✏️Note: This is only applicable when using vector search, and is ignored otherwise.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with the new sort vector settings.
Optional includeSortVector: booleanWhether the sort vector should be fetched on the first API call
A new cursor with the new sort vector inclusion setting.
const cursor = table.find({ name: 'John' })
.sort({ $vectorize: 'name' })
.includeSortVector();
// The cursor will return the sort vector used
// Here, it'll be the embedding for the vector created from the name 'John'
const sortVector = await cursor.getSortVector();
sortVector; // DataAPIVector([...])
Sets the initial page state for the cursor, allowing you to resume fetching results from a specific point.
This method provides direct access to the underlying pagination mechanism, allowing you to handle pagination manually instead of relying solely on the cursor's iteration methods.
This is primarily useful when pagination is driven by a separate process (e.g. in client/server architectures where the client maintains the page state).
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with the new initial page state.
⚠️Warning: When resuming a cursor using a page state, all other cursor options (filter, sort, limit, etc.) should remain exactly the same as those used to generate the original page state. Using different options with the same page state can lead to unexpected results or errors.
⚠️Warning: Do not "resume" a cursor which has a
nullpage state—it would be equivalent to closing the cursor before it has even started. If you want a cursor with no page state, useundefinedinstead.
Optional initialPageState: stringThe page state to resume from, or undefined to start from the beginning
A new cursor with the initial page state set
// Server-side code
async function getPageOfResults(pageState?: string) {
const cursor = collection.find({ status: 'active' })
.initialPageState(pageState);
const page = await cursor.fetchNextPage();
return {
nextPageState: page.nextPageState,
results: page.result,
};
}
// Client can then use the nextPageState to fetch subsequent pages
null initial page states are rejected to prevent the user from accidentally creating an infinite loop of fetching.
FindCursor.fetchNextPage
Sets the maximum number of records to return.
If limit == 0, there will be no limit on the number of records returned (beyond any that the Data API may itself enforce).
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new
limit.
Optional limit: numberThe limit for this cursor.
A new cursor with the new limit set.
await collection.insertMany([
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
]);
const cursor = collection.find({})
.limit(1);
// The cursor will return only one record
const all = await cursor.toArray();
all.length === 1; // true
Fetches the next record from the cursor. Returns null if there are no more records to fetch.
nullnull will be returnedThe next record, or null if there are no more records.
const cursor = collection.find({ name: 'John' });
// Get the first record
const john = await cursor.next();
// Get the next record (or null if no more records)
const nextRecord = await cursor.next();
// Exhaust the cursor
let doc;
while ((doc = await cursor.next()) !== null) {
console.log(doc);
}
Rewinds the cursor to its uninitialized state, clearing the buffer and any state.
Any configuration set on the cursor will remain, but iteration will start from the beginning, sending new queries to the server, even if the resultant data was already fetched by the cursor.
const cursor = collection.find({}).sort({ name: 1 });
// Read some data
const first = await cursor.next();
// Rewind the cursor
cursor.rewind();
// Start again from the beginning
const firstAgain = await cursor.next();
// first and firstAgain are the same record
Rewinding a cursor is different from cloning it. Cloning creates an independent new cursor with the same state and configuration as the original, while rewinding resets the current cursor to its initial state.
See AbstractCursor.clone for more information on cloning.
AbstractCursor.clone
Sets the number of records to skip before returning. Must be used with FindCursor.sort.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new
skip.
Optional skip: numberThe skip for the cursor query.
A new cursor with the new skip set.
await collection.insertMany([
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
]);
const cursor = collection.find({})
.sort({ age: -1 })
.skip(1);
// The cursor will skip the first record and return the second
const secondOldest = await cursor.next();
secondOldest.age === 25; // true
Sets the sort criteria for prioritizing records.
🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new
sort.
Optional sort: SortThe sort order to prioritize which records are returned.
A new cursor with the new sort set.
await collection.insertMany([
{ name: 'John', age: 30 },
{ name: 'Jane', age: 25 },
]);
const cursor = collection.find({})
.sort({ age: -1 });
// The cursor will return records sorted by age in descending order
const oldest = await cursor.next();
oldest.age === 30; // true
Returns an array of all matching records in the cursor.
⚠️Warning: The user should ensure that there is enough memory to store all records in the cursor.
⚠️Warning: There'll only be partial results if the cursor has been consumed prior. You may use AbstractCursor.rewind to reset the cursor.
An array of all records in the cursor.
const cursor = collection.find({ department: 'Engineering' });
// Get all matching records as an array
const engineers = await cursor.toArray();
console.log(`Found ${engineers.length} engineers`);
// For a large result set, consider using lazy iteration instead
for await (const doc of cursor.rewind()) {
// Process one document at a time
}
Overview
A lazy iterator over the results of a
findoperation on a Collection.Typing
In full, the cursor is typed as
CollectionFindCursor<T, TRaw>, whereTis the type of the mapped records, andTRawis the type of the raw records before any mapping.If no mapping function is provided,
TandTRawwill be the same type. Mapping is done using the CollectionFindCursor.map method.Options
Options may be set either through the
find({}, options)method, or through the various fluent builder methods, which, unlike Mongo, do not mutate the existing cursor, but rather return a new, uninitialized cursor with the new option(s) set.Example
See