Customize Query
-
Use the below customization methods over a specific query.
-
The customization methods can be set for both dynamic and index queries.
-
A query can be customized on the Store or Session level by calling various methods from the rich API.
Learn more in Subscribing to Events. -
Customization methods available:
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
-
Use
after_stream_executed
to retrieve a raw (blittable) result of the streaming query. -
Learn more in how to stream query results.
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 toFROM_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 retrievedQueryTimings
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.
Callingwait_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 |