Customize Query



on ("beforeQueryExecuted")

  • Use on("beforeQueryExecuted") to customize the query just before it is executed.

Example

const results = await session
     // Query an index
    .query(BlogPost, BlogPosts_ByTag)
     // Provide a callback for the 'beforeQueryExecuted' event 
    .on("beforeQueryExecuted", query => {
        // Can modify query parameters
        query.skipDuplicateChecking = true;
        // Can apply any needed action, e.g. write to log/console
        console.log(`Query to be executed is: ${query.query}`);
    })
    .all();
class BlogPosts_ByTag extends AbstractJavaScriptIndexCreationTask {
    constructor() {
        super();

        this.map(BlogPost, b => {
            const result = [];

            b.tags.forEach(item => {
                result.push({
                    tag: item
                });
            });

            return result;

            // This fanout index outputs multiple index entries per each document,
            // (an index-entry per tag in from the tags list).            
            // The query can be customized to return the documents without the duplicates,
            // (see the query example in the first tab).  
        })
    }
}

class BlogPost {
    constructor() {
        this.id = null;
        this.title = null;
        this.body = null;
        this.tags = null;
    }
}

class TagResult {
    constructor() {
        this.tag = null;
    }
}

Syntax

on("beforeQueryExecuted", eventHandler);
Parameters Type Description
eventHandler (query) => void A callback method that is invoked when the beforeQueryExecuted event is emitted.
The passed query param is of type IndexQuery.

on ("afterQueryExecuted")

  • Use on("afterQueryExecuted") to access the raw query result after it is executed.

Example

let queryDuration = 0;

const results = await session
    .query({ collection: "employees" })
     // Provide a callback for the 'afterQueryExecuted' event 
    .on("afterQueryExecuted", rawResult => {
        // Can access the raw query result
        queryDuration = rawResult.durationInMs
        // Can apply any needed action, e.g. write to log/console
        console.log(`${rawResult.lastQueryTime}`);
     })
    .all();

Syntax

on("afterQueryExecuted", eventHandler);
Parameters Type Description
eventHandler (queryResult) => void A callback method that is invoked when the afterQueryExecuted event is emitted.
The passed query param is of type QueryResult.

noCaching

  • By default, query results are cached.

  • You can use the noCaching customization to disable query caching.

Example

const results = await session
    .query({ collection: "employees" })
    .whereEquals("firstName", "Robert")
     // Add a call to 'noCaching'
    .noCaching()
    .all();

Syntax

noCaching();

noTracking

  • By default, the Session tracks all changes made to all entities that it has either loaded, stored, or queried for.

  • You can use the noTracking customization to disable entity tracking.

  • See disable entity tracking for all other options.

Example

const results = await session
    .query({ collection: "employees" })
    .whereEquals("firstName", "Robert")
    // Add a call to 'noTrcking'
    .noTracking()
    .all();

Syntax

noTracking();

projectionBehavior

  • By default, when querying an index, and projecting query results
    (projecting means the query returns only specific document fields instead of the full document)
    then the server will try to retrieve the fields' values from the fields stored in the index.

  • If the index does Not store those fields then the fields' values will be retrieved from the documents store.

  • Use the selectFields method to customize and modify this behavior for the specified fields.

  • Note:
    Entities resulting from a projecting query are Not tracked by the session.
    Learn more about projections in:

Example

// The projection class: 
class EmployeeProjectedDetails {
    constructor() {
        this.fullName = null;
    }
}

// Define a query with a projection
const query = session
     // Query an index that has stored fields
    .query(Employee, Employee_ByFullName)
     // Use 'selectFields' to project the query results
     // Pass the requested projection behavior (3'rd param)
    .selectFields(["fullName"], EmployeeProjectedDetails, "FromDocumentOrThrow")
    .all();

// * Field 'fullName' is stored in the index.
//   However, the server will try to fetch the value from the document 
//   since the default behavior was modified to `FromDocumentOrThrow`.

// * An exception will be thrown -
//   since an 'Employee' document does not contain the property 'fullName'.
//   (based on the Northwind sample data).        
class Employee_ByFullName extends AbstractJavaScriptIndexCreationTask {
    constructor() {
        super();

        this.map(Employee, e => {
            return {
                fullName: e.firstName + " " + e.lastName
            }
        })

        // Store field 'fullName' in the index
        this.store("fullName", "Yes");
    }
}

Syntax

selectFields(properties, projectionClass, projectionBehavior);
Parameters Type Description
properties string[] Fields' names for which to fetch values
projectionClass object The projected results class
projectionBehavior string The requested projection behavior, see available options below
  • Default
    Retrieve values from the stored index fields when available.
    If fields are not stored then get values from the document,
    a field that is not found in the document is skipped.
  • FromIndex
    Retrieve values from the stored index fields when available.
    A field that is not stored in the index is skipped.
  • FromIndexOrThrow
    Retrieve values from the stored index fields when available.
    An exception is thrown if the index does not store the requested field.
  • FromDocument
    Retrieve values directly from the documents store.
    A field that is not found in the document is skipped.
  • FromDocumentOrThrow
    Retrieve values directly from the documents store.
    An exception is thrown if the document does not contain the requested field.

randomOrdering

  • Use RandomOrdering to order the query results randomly.

  • More ordering options are available in this Sorting article.

Example

const results = await session
    .query({ collection: "employees" })
    // Add a call to 'randomOrdering', can pass a seed
    .randomOrdering("123")
    .all();

Syntax

randomOrdering();
randomOrdering(seed);
Parameters Type Description
seed string Order the search results randomly using this seed.
Useful when executing repeated random queries.

timings

  • Use Timings to get detailed stats of the time spent by the server on each part of the query.

  • The timing statistics will be included in the query results.

  • Learn more in how to include query timings.

Example

let timingsResults;

const results = await session.query({ collection: "Products" })
    .whereEquals("firstName", "Robert")
     // Call 'timings', pass a callback function
     // Output param 'timingsResults' will be filled with the timings details when query returns 
    .timings(t => timingsResults = t)
    .all();

Syntax

timings(timingsCallback)
Parameters Type Description
timings QueryTimings An out param that will be filled with the timings results
QueryTimings
DurationInMs long Total duration
Timings IDictionary<string, QueryTimings> Dictionary with QueryTimings info per time part

waitForNonStaleResults

  • All queries in RavenDB provide results using an index, even when you don't specify one.
    See detailed explanation in Queries always provide results using an index.

  • Use waitForNonStaleResults to instruct the query to wait for non-stale results from the index.

  • A TimeoutException will be thrown if the query is not able to return non-stale results within the specified
    (or default) timeout.

  • Note: This feature is Not available when streaming the query results.
    Calling waitForNonStaleResults with a streaming query will throw an exception.

  • Learn more about stale results in stale indexes.

Example

const results = await session.query({ collection: "Products" })
    .whereEquals("firstName", "Robert")
     // Call 'waitForNonStaleResults', 
     // Optionally, pass the time to wait. Default is 15 seconds.
    .waitForNonStaleResults(10_000)
    .all();

Syntax

waitForNonStaleResults();
waitForNonStaleResults(waitTimeout);
Parameters Type Description
waitTimeout number Time (ms) to wait for an index to return non-stale results.
Default is 15 seconds.