Class FindAndRerankCursor<T, TRaw>Abstract

Overview (preview)

A lazy iterator over the results of some generic findAndRerank operation on the Data API.

⚠️Warning: Shouldn't be directly instantiated, but rather spawned via Collection.findAndRerank.


Typing

✏️Note: You may generally treat the cursor as if it were typed as FindAndRerankCursor<T>.

If you're using a projection, it is heavily recommended to provide an explicit type representing the type of the document after projection.

In full, the cursor is typed as FindAndRerankCursor<T, TRaw>, where

  • T is the type of the mapped records, and
  • TRaw is the type of the raw records before any mapping.

If no mapping function is provided, T and TRaw will be the same type. Mapping is done using the FindAndRerankCursor.map method.


Options

Options may be set either through the findAndRerank({}, 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

const collection = db.collection('hybrid_coll');

const cursor = collection.findAndRerank({}, {
sort: { $hybrid: 'what is a car?' },
includeScores: true,
});

for await (const res of cursor) {
console.log(res.document);
console.log(res.scores);
}

See

CollectionFindAndRerankCursor

Type Parameters

Hierarchy (view full)

Constructors

Properties

_mapping?: ((doc) => T)

Type declaration

    • (doc): T
    • Parameters

      • doc: any

      Returns T

_state: CursorState = 'idle'
_timeoutOptions: CommandOptions<Required<CommandOptionsSpec>>
bufferedCount: "ERROR: `.bufferedCount()` has been renamed to be simply `.buffered()`"

This temporary error-ing property exists for migration convenience, and will be removed in a future version.

Deprecated

  • .bufferedCount() has been renamed to simply be .buffered().
readBufferedDocuments: "ERROR: `.readBufferedDocuments()` has been renamed to be `.consumeBuffer()`"

This temporary error-ing property exists for migration convenience, and will be removed in a future version.

Deprecated

  • .readBufferedDocuments() has been renamed to be .consumeBuffer().
InternalNextPageOptions: {
    commandName: "findAndRerank";
    commandOptions: readonly ["limit", "hybridLimits", "rerankOn", "rerankQuery", "includeScores", "includeSortVector"];
    mapPage<TRaw>(page, raw): {
        nextPageState: null | string;
        result: TRaw[];
        sortVector: undefined | DataAPIVector;
    };
} = ...

Type declaration

Accessors

  • get state(): CursorState
  • Overview

    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.

    Returns CursorState

    Example

    const cursor = collection.find({});
    console.log(cursor.state); // 'idle'

    await cursor.next();
    console.log(cursor.state); // 'started'

    cursor.close();
    console.log(cursor.state); // 'closed'

    See

    CursorState

Methods

  • Overview

    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.


    Behavior
    • If the cursor is uninitialized, it will be initialized
    • If the consumer breaks, iteration will stop early
    • If the cursor is closed, this method will throw a CursorError
    • It will close the cursor when iteration is complete, even if it was broken early
    • If no records are found, no error will be thrown, and the iterator will simply finish

    Returns AsyncGenerator<T, void, void>

    Example

    const 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'
  • Overview

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

    Returns number

    The number of raw records currently in the buffer.

    Example

    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

    See

    AbstractCursor.consumed

  • Overview

    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.

    Returns this

    A new cursor with the same configuration as the current cursor.

    Example

    const cursor = collection.findAndRerank({ age: { $gt: 30 } })
    .sort({ $hybrid: 'old man' });

    // 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 vs Rewinding

    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 FindAndRerankCursor.rewind for more information on rewinding.

    See

    FindAndRerankCursor.rewind

  • Overview

    Closes the cursor. The cursor will be unusable after this method is called, or until AbstractCursor.rewind is called.

    Returns void

    Example

    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

    See

    AbstractCursor.rewind - To reset a closed cursor to make it usable again

  • Overview

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

    Parameters

    • Optional max: number

      The optional max number of records to read from the buffer.

    Returns RerankedResult<TRaw>[]

    The records read from the buffer.

    Example

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

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

    Returns number

    The number of records that have been read from the cursor.

    Example

    const cursor = collection.find({});
    console.log(cursor.consumed()); // 0

    await cursor.next();
    console.log(cursor.consumed()); // 1

    See

    AbstractCursor.buffered

  • Overview 🚨

    Fetches the next complete page of results from the server and returns it directly.

    🚨Important: findAndRerank operations are not currently paginated, and as such, this construct mainly exists for consistency with FindCursor.fetchNextPage.

    Regardless, the page state mechanism is still full functional on the client side, in case it is available in the future.

    See FindCursor.fetchNextPage for more information on fetching the next page.

    Returns Promise<FindAndRerankPage<T>>

    A page object containing the results, the next page state, and optionally the sort vector.

    See

    • FindAndRerank.initialPageState
    • FindAndRerank.toArray
  • Overview

    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.

    Parameters

    • filter: Filter

      A filter to select which records to return.

    Returns this

    A new cursor with the new filter set.

    Example

    await table.insertOne({ name: 'John', ... });

    const cursor = table.findAndRerank({})
    .sort({ $hybrid: 'big burly man' })
    .filter({ name: 'John' });

    // The cursor will only return records with the name 'John'
    const { document: john } = await cursor.next();
    john.name === 'John'; // true
  • Overview

    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.


    Behavior
    • If the cursor is uninitialized, it will be initialized
    • If the consumer returns false or Promise<false>, iteration will stop early
    • If the cursor is closed, this method will throw a CursorError
    • It will close the cursor when iteration is complete, even if it was stopped early
    • If no records are found, no error will be thrown, and the iterator will simply finish

    Parameters

    • consumer: ((doc) => boolean | Promise<boolean>) | ((doc) => void | Promise<void>)

      The consumer to call for each record. Return false to stop iteration.

    Returns Promise<void>

    A promise that resolves when iteration is complete.

    Example

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

    Retrieves the vector used to perform the vector search, if applicable.

    🚨Important: This will only return a non-null value if FindAndRerankCursor.includeSortVector is set.

    Returns Promise<null | DataAPIVector>

    The sort vector used to perform the vector search, or null if not applicable.

    Example

    // Using $vector
    const vector = new DataAPIVector([0.1, 0.2, 0.3]);
    const cursor = collection.findAndRerank({})
    .sort({ $hybrid: { $vector: vector, ... } })
    .includeSortVector();

    const sortVector = await cursor.getSortVector();
    // Returns the same vector used in the sort

    // Using $vectorize
    const cursor = collection.findAndRerank({})
    .sort({ $hybrid: { $vectorize: 'some text', ... } })
    .includeSortVector();

    const sortVector = await cursor.getSortVector();
    // Returns the vector generated from the text

    Method Behavior

    This method will:

    • Return null if includeSortVector was not set to true
    • Return the original vector if sort: { $hybrid: { $vector } } was used
    • Return the generated vector if sort: { $hybrid: { $vectorize } } was used

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

  • Overview

    Tests if there is a next record in the cursor.


    Behavior
    • If the cursor is uninitialized, it will be initialized
    • If the cursor is closed, this method will return false
    • It will close the cursor when there are no more records to fetch

    Returns Promise<boolean>

    Whether or not there is a next record.

    Example

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

    Sets the maximum number of records to consider from the underlying vector and lexical searches.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new limit.


    Different formats

    Either a single number, or an object may be provided as a limit definition.

    If a single number is specified, it applies to both the vector and lexical searches.

    To set different limits for the vector and lexical searches, an object containing limits for each vector and lexical column must be provided.

    • For collections, it looks like this: { $vector: number, $lexical: number }

    Parameters

    • hybridLimits: number | Record<string, number>

      The hybrid limits for this cursor.

    Returns this

    A new cursor with the new hybrid limits set.

    Example

    await collection.insertMany([
    { name: 'John', age: 30, $vectorize: 'an elder man', $lexical: 'an elder man' },
    { name: 'Jane', age: 25, $vectorize: 'a young girl', $lexical: 'a young girl' },
    ]);

    const cursor = collection.findAndRerank({})
    .sort({ $hybrid: 'old man' })
    .hybridLimits(1);

    // The cursor will return only one record
    const all = await cursor.toArray();
    all.length === 1; // true
  • Overview

    Determines whether the RerankedResult.scores is returned for each document.

    If this is not set, then the scores will be an empty object for each document.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with new score settings.

    Parameters

    • Optional includeScores: boolean

      Whether the scores should be included in the result.

    Returns this

    A new cursor with the new scores inclusion setting.

    Example

    const cursor = table.findAndRerank({ name: 'John' })
    .sort({ $hybrid: 'old man' })
    .includeScores();

    for await (const res of cursor) {
    console.log(res.document);
    console.log(res.scores);
    }
  • Overview

    Sets whether the sort vector should be fetched on the very first API call.

    Note that this is a requirement to use FindAndRerankCursor.getSortVector—it'll unconditionally return null if this is not set to true.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with the new sort vector settings.

    Parameters

    • Optional includeSortVector: boolean

      Whether the sort vector should be fetched on the first API call

    Returns this

    A new cursor with the new sort vector inclusion setting.

    Example

    const cursor = table.findAndRerank({})
    .sort({ $hybrid: 'old man' })
    .includeSortVector();

    // The cursor will return the sort vector used
    // Here, it'll be the embedding for the vector created from the term 'old man'
    const sortVector = await cursor.getSortVector();
    sortVector; // DataAPIVector([...])
  • Overview 🚨

    Sets the initial page state for the cursor, allowing you to resume fetching results from a specific point.

    🚨Important: findAndRerank operations are not currently paginated, and as such, this construct mainly exists for consistency with FindCursor.initialPageState.

    Regardless, the page state mechanism is still full functional on the client side, in case it is available in the future.

    See FindCursor.initialPageState for more information on, and warnings about, the initial page state.

    Parameters

    • Optional initialPageState: string

      The page state to resume from, or undefined to start from the beginning

    Returns this

    A new cursor with the initial page state set

    Remarks

    null initial page states are rejected to prevent the user from accidentally creating an infinite loop of fetching.

    See

    FindAndRerankCursor.fetchNextPage

  • Overview

    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.

    Parameters

    • limit: number

      The limit for this cursor.

    Returns this

    A new cursor with the new limit set.

    Example

    await collection.insertMany([
    { name: 'John', age: 30, $vectorize: 'an elder man', $lexical: 'an elder man' },
    { name: 'Jane', age: 25, $vectorize: 'a young girl', $lexical: 'a young girl' },
    ]);

    const cursor = collection.findAndRerank({})
    .sort({ $hybrid: 'old man' })
    .limit(1);

    // The cursor will return only one record
    const all = await cursor.toArray();
    all.length === 1; // true
  • Overview

    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.

    Type Parameters

    • R

    Parameters

    • map: ((doc) => R)

      The mapping function to apply to all records.

        • (doc): R
        • Parameters

          • doc: T

          Returns R

    Returns FindAndRerankCursor<R, TRaw>

    A new cursor with the new mapping set.

    Example

    const cursor = table.findAndRerank({});
    .sort({ $hybrid: 'old man' })
    .map(res => res.document);
    .map(row => row.name.toLowerCase());

    // T is `string` because the mapping function returns a string
    const name = await cursor.next();
    name === 'john'; // true
  • Overview

    Fetches the next record from the cursor. Returns null if there are no more records to fetch.


    Behavior
    • If the cursor is uninitialized, it will be initialized
    • If the cursor is closed, this method will return null
    • It will close the cursor when there are no more records to fetch
    • If no records are found, no error will be thrown, and null will be returned

    Returns Promise<null | T>

    The next record, or null if there are no more records.

    Example

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

    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.

    Type Parameters

    Parameters

    • projection: Projection

      Specifies which fields should be included/excluded in the returned records.

    Returns FindAndRerankCursor<RerankedResult<RRaw>, RRaw>

    A new cursor with the new projection set.

    Example

    const cursor = table.findAndRerank({ name: 'John' }).sort(...);

    // T is `RerankedResult<Partial<Schema>>` because the type is not specified
    const rawProjected = cursor.project({ id: 0, name: 1 });

    // T is `RerankedResult<{ name: string }>`
    const projected = cursor.project<{ name: string }>({ id: 0, name: 1 });

    // You can also chain instead of using intermediate variables
    const fluentlyProjected = table
    .findAndRerank({ name: 'John' })
    .sort(...)
    .project<{ name: string }>({ id: 0, name: 1 });
    .map(res => res.document)
    .map(row => row.name);
  • Overview

    Specifies the document field to use for the reranking step. Often used with FindAndRerankCursor.rerankQuery.

    Optional if you query through the $vectorize field instead of the $vector field; otherwise required.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new rerankOn.


    Under the hood

    Once the underlying vector and lexical searches complete, the reranker compares the rerankQuery text with each document's rerankOn field.

    The reserved $lexical field is often used for this parameter, but you can specify any field that stores a string.

    Any document lacking the field is excluded.


    Parameters

    • rerankOn: string

      The document field to use for the reranking step.

    Returns this

    A new cursor with the new rerankOn set.

    Example

    const cursor = await coll.findAndRerank({})
    .sort({ $hybrid: { $vector: vector([...]), $lexical: 'what is a dog?' } })
    .rerankOn('$lexical')
    .rerankQuery('I like dogs');

    for await (const res of cursor) {
    console.log(res.document);
    }
  • Overview

    Specifies the query text to use for the reranking step. Often used with FindAndRerankCursor.rerankOn.

    Optional if you query through the $vectorize field instead of the $vector field; otherwise required.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new rerankQuery.


    Under the hood

    Once the underlying vector and lexical searches complete, the reranker compares the rerankQuery text with each document's rerankOn field.


    Parameters

    • rerankQuery: string

      The query text to use for the reranking step.

    Returns this

    A new cursor with the new rerankQuery set.

    Example

    const cursor = await coll.findAndRerank({})
    .sort({ $hybrid: { $vector: vector([...]), $lexical: 'what is a dog?' } })
    .rerankOn('$lexical')
    .rerankQuery('I like dogs');

    for await (const res of cursor) {
    console.log(res.document);
    }
  • Overview

    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.

    Returns void

    Example

    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 vs Cloning

    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.

    See

    AbstractCursor.clone

  • Overview

    Sets the sort criteria for prioritizing records.

    🚨Important: This option must be set, and must contain a $hybrid key.

    🚨Important: This method does NOT mutate the cursor; it returns a new cursor with a new sort.


    The $hybrid key

    The $hybrid key is a special key that specifies the query(s) to use for the underlying vector and lexical searches.

    If your collection doesn't have vectorize enabled, you must pass separate query items for $vector and $lexical:

    • { $hybrid: { $vector: vector([...]), $lexical: 'A house on a hill' } }

    If your collection has vectorize enabled, you can query through the $vectorize field instead of the $vector field. You can also use a single search string for both the $vectorize and $lexical queries.

    • { $hybrid: { $vectorize: 'A tree in the woods', $lexical: 'A house on a hill' } }
    • { $hybrid: 'A tree in the woods' }

    Parameters

    • sort: HybridSort

      The hybrid sort criteria to use for prioritizing records.

    Returns this

    A new cursor with the new sort set.

    Example

    await collection.insertMany([
    { name: 'John', age: 30, $vectorize: 'an elder man', $lexical: 'an elder man' },
    { name: 'Jane', age: 25, $vectorize: 'a young girl', $lexical: 'a young girl' },
    ]);

    const cursor = collection.findAndRerank({})
    .sort({ $hybrid: 'old man' });

    // The cursor will return records sorted by the hybrid query
    const { document: oldest } = await cursor.next();
    oldest.nane === 'John'; // true
  • Overview

    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.


    Behavior
    • If the cursor is uninitialized, it will be initialized
    • If the cursor is closed, this method will throw a CursorError
    • It will close the cursor when fetching is complete
    • If no records are found, no error will be thrown, and an empty array will be returned

    Returns Promise<T[]>

    An array of all records in the cursor.

    Example

    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
    }