Customize Query



before_query_executed

  • Use before_query_executed to customize the query just before it is executed.

Example

def __before_query_executed_callback(query: IndexQuery):
    # Can modify query parameters
    query.skip_duplicate_checking = True
    # Can apply any needed action, e.g. write to log
    logger.info(f"Query to be executed is: {query.query}")

results = list(
    session.query(object_type=Employee)
    # Call 'add_before_query_executed_listener'
    .add_before_query_executed_listener(__before_query_executed_callback).where_equals(
        "first_name", "Robert"
    )
)
def __before_query_executed_callback(query: IndexQuery):
    # Can modify query parameters
    query.skip_duplicate_checking = True
    # Can apply any needed action, e.g. write to log
    logger.info(f"Query to be executed is: {query.query}")

results = list(
    session.advanced.raw_query("from 'Employees' where FirstName == 'Robert'")
    # Call 'add_before_query_executed_listener'
    .add_before_query_executed_listener(__before_query_executed_callback)
)

Syntax

def add_before_query_executed_listener(self, action: Callable[[IndexQuery], None]) -> DocumentQuery[_T]: ...
Parameters Type Description
action Callable[[IndexQuery], None] An action method that operates on the query.
The query is passed in the IndexQuery param.

after_query_executed

  • Use after_query_executed to access the raw query result after it is executed.

Example

def __after_query_executed_callback(raw_result: QueryResult):
    # Can access the raw query result
    query_duration = raw_result.duration_in_ms
    # Can apply any needed action, e.g. write to log
    logger.info(f"{raw_result.last_query_time}")

results = list(
    session.query(object_type=Employee)
    # Call 'add_after_query_executed_listener'
    .add_after_query_executed_listener(__after_query_executed_callback)
)
def __after_query_executed_callback(raw_result: QueryResult):
    # Can access the raw query result
    query_duration = raw_result.duration_in_ms
    # Can apply any needed action, e.g. write to log
    logger.info(f"{raw_result.last_query_time}")

result = list(
    session.advanced.raw_query("from 'Employees'")
    # Call 'add_after_query_executed_listener'
    .add_after_query_executed_listener(__after_query_executed_callback)
)

Syntax

def add_after_query_executed_listener(self, action: Callable[[QueryResult], None]) -> DocumentQuery[_T]: ...
Parameters Type Description
action Callable[[QueryResult], None] An action method that receives the raw query results.
The query result is passed in the QueryResult param.

after_stream_executed

Syntax

def add_after_stream_executed_listener(self, action: Callable[[dict], None]) -> DocumentQuery[_T]: ...
Parameters Type Description
action Callable[[dict], None]) An action method that recieves a single stream query result.
The stream result is passed in the dict param.

no_caching

  • By default, query results are cached.

  • You can use the no_caching customization method to disable query caching.

  • Learn more in disable caching per session.

Example

results = list(
    session.query(object_type=Employee)
    # Call 'no_caching'
    .no_caching().where_equals("first_name", "Robert")
)
results = list(
    session.advanced.raw_query("from 'Employees' where first_name == 'Robert'")
    # Call 'no_caching'
    .no_caching()
)

Syntax

def no_caching(self) -> DocumentQuery[_T]: ...

no_tracking

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

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

  • See disable entity tracking for all other options.

Example

results = list(
    session.query(object_type=Employee)
    # Call 'no_tracking`
    .no_tracking().where_equals("first_name", "Robert")
)
results = list(
    session.advanced.raw_query("from 'Employees' where first_name == 'Robert'")
    # Call 'no_tracking'
    .no_tracking()
)

Syntax

def no_tracking(self) -> DocumentQuery[_T]: ...

projection

  • By default, when querying an index and projecting query results,
    the server will try to retrieve field values from the fields stored in the index.

    Projecting means the query returns only specific document fields instead of the full document.

  • If these fields are not stored in the index, the field values will be retrieved from the documents.

  • Use the select_fields method to customize and modify this behavior.

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

Example

results = list(
    session.query_index_type(Employees_ByFullName, Employees_ByFullName.IndexEntry)
    # Pass the requested projection behavior to the 'select_fields' method
    # and specify the field that will be returned to the projection
    .select_fields(
        Employees_ByFullName.IndexEntry,
        "full_name",
        projection_behavior=ProjectionBehavior.FROM_INDEX_OR_THROW,
    )
)
results = list(
    session.advanced.raw_query(
        "from index 'Employees/ByFullName' select full_name", Employees_ByFullName.IndexEntry
    ).projection(ProjectionBehavior.FROM_DOCUMENT_OR_THROW)
)
class Employees_ByFullName(AbstractIndexCreationTask):
    class IndexEntry:
        def __init__(self, full_name: str = None):
            self.full_name = full_name

    def __init__(self):
        super().__init__()
        self.map = (
            "docs.Employees.Select(employee => new { "
            "    full_name = (employee.first_name + ' ' + employee.last_name)"
            "})"
        )
        self._store("full_name", FieldStorage.YES)

In the above example:

  • The 'full_name' field is stored in the index (see index definition in the rightmost tab).
    However, the server will try to fetch the value from the document since the default behavior was modified to FROM_DOCUMENT_OR_THROW.
  • An exception will be thrown since an 'Employee' document does not contain the 'full_name' property.
    (based on the Northwind sample data).

random_ordering

  • Use random_ordering to order the query results randomly.

  • Learn here about additional ordering options.

Example

results = list(
    session.query(object_type=Employee)
    # Call 'random_ordering'
    .random_ordering()
)
results = list(
    session.advanced
    # Define an RQL query that orders the results randomly
    .raw_query("from 'Employees' order by random()", Employee)
)

Syntax

def random_ordering(self, seed: str = None) -> DocumentQuery[_T]: ...
Parameters Type Description
seed str Order the search results randomly using this seed.
Useful when executing repeated random queries.

timings

  • When executing a query, you can retrieve query statistics that include the time spent by the server on each part of the query.

  • To do this, define a callback function that takes QueryTimings as an argument and applies whatever logic you want to apply.

  • Then pass your function as an argument to the query.timings method and use the retrieved QueryTimings object.

  • Learn more in how to include query timings.

Example

def __timings_callback(timings: QueryTimings):
    logger.log(logging.DEBUG, timings.duration_in_ms)

results = list(
    session.query(object_type=Employee).where_equals("first_name", "Robert")
    # Call 'timings'.
    # Provide a callback for the timings result - interact with QueryTimings inside the callback
    .timings(__timings_callback)
)
def __timings_callback(timings: QueryTimings):
    logger.log(logging.DEBUG, timings.duration_in_ms)

results = list(
    session.advanced.raw_query("from 'Employees' where first_name == 'Robert'")
    # Call 'timings'.
    # Provide a callback for the timings result - interact with QueryTimings inside the callback
    .timings(__timings_callback)
)

Syntax

def timings(self, timings_callback: Callable[[QueryTimings], None]) -> DocumentQuery[_T]: ...
Parameters Type Description
timings_callback Callable[[QueryTimings], None] An action that will be called with the timings results

wait_for_non_stale_results

  • All RavenDB queries provide results using an index, even when an index is not specified.
    See detailed explanation in Queries always provide results using an index.

  • If wait_for_non_stale_results is used, the query will wait for non-stale results from the index.

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

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

  • Learn more about stale results in stale indexes.

Example

results = list(
    session.query(object_type=Employee)
    # Call 'wait_for_non_stale_results`
    .wait_for_non_stale_results(timedelta(seconds=10)).where_equals("first_name", "Robert")
)
results = list(
    session.advanced.raw_query("from 'Employees' where first_name == 'Robert'", Employee)
    # Call 'wait_for_non_stale_results`
    .wait_for_non_stale_results(timedelta(seconds=10))
)

Syntax

def wait_for_non_stale_results(self, wait_timeout: timedelta = None) -> DocumentQuery[_T]: ...
Parameters Type Description
wait_timeout timedelta Time to wait for non-stale results.
Default: 15 seconds

Methods return value

All of the above customization methods return the following:

document_query return value
DocumentQuery[_T] Returns self for easier method chaining