Query Overview


  • Queries in RavenDB can be written with either of the following:

    • Using a rich API via session's query method
    • Using a low-level API via session's document_query method
    • Using RQL -
      • when querying via session's raw_query method
      • when querying through Studio's Query view
  • Queries defined with query or document_query are translated by the RavenDB client to RQL
    when sent to the server.


  • All queries in RavenDB use an index to provide results, even when you don't specify one.
    Learn more below.

  • Queries that do Not specify which index to use are called Dynamic Queries.
    This article displays examples of dynamic queries only.
    For examples showing how to query an index see querying an index.


  • The entities returned by the query are 'loaded' and tracked by the Session.
    Entities will Not be tracked when:

  • Query results are cached by default. To disable query caching see NoCaching.

  • Queries are timed out after a configurable time period. See query timeout.



Queries always provide results using an index

  • Queries always use an index to provide fast results regardless of the size of your data.

  • When a query reaches a RavenDB instance, the instance calls its query optimizer to analyze the query
    and determine which index should be used to retrieve the requested data.

  • Indexes allow to provide query results without scanning the entire dataset each and every time.
    Learn more about indexes in indexes overview.

We differentiate between the following 3 query scenarios:

  • Index query
  • Dynamic query
  • Full collection query

For each scenario, a different index type will be used.

1. Query an existing index:

  • Query type: Index query
    Index used: Static-index

  • You can specify which STATIC-index the query will use.

  • Static indexes are defined by the user, as opposed to auto-indexes that are created by the server
    when querying a collection with some filtering applied. See Static-index vs Auto-index.

  • Example RQL:   from index "Employees/ByFirstName" where FirstName == "Laura"
    See more examples in querying an index.

2. Query a collection - with filtering:

  • Query type: Dynamic Query
    Index used: Auto-index

  • When querying a collection without specifying an index and with some filtering condition
    (other than just the document ID) the query-optimizer will analyze the query to see if an AUTO-index
    that can answer the query already exists, i.e. an auto-index on the collection queried with index-fields that match those queried.

  • If such auto-index (Not a static one...) is found, it will be used to fetch the results.

  • Else, if no relevant auto-index is found,
    the query-optimizer will create a new auto-index with fields that match the query criteria.
    At this time, and only at this time, the query will wait for the auto-indexing process to complete.
    Subsequent queries that target this auto-index will be served immediately.

  • Note: if there exists an auto-index that is defined on the collection queried
    but is indexing a different field than the one queried on,
    then the query-optimizer will create a new auto-index that merges both the
    fields from the existing auto-index and the new fields queried.

  • Once the newly created auto-index is done indexing the data,
    the old auto-index is removed in favor of the new one.

  • Over time, an optimal set of indexes is generated by the query optimizer to answer your queries.

  • Example RQL:   from Employees where FirstName == "Laura"
    See more examples below.


  • Note: Counters and Time series are an exception to this flow.
    Dynamic queries on counters and time series values don't create auto-indexes.
    However, a static-index can be defined on Time series and Counters.

3. Query a collection - query full collection | query by ID:

  • Query type: Full collection Query
    Index used: The raw collection (internal storage indexes)

  • Full collection query:

    • When querying a collection without specifying an index and with no filtering condition,
      then all documents from the specified collection are returned.

    • RavenDB uses the raw collection documents in its internal storage indexes as the source for this query.
      No auto-index is created.

    • Example RQL:   from Employees

  • Query by document ID:

    • When querying a collection only by document ID or IDs,
      then similar to the full collection query, no auto-index is created.

    • RavenDB uses the raw collection documents as the source for this query.

    • Example RQL:   from Employees where id() == "employees/1-A"
      See more examples below.

session.query

  • The simplest way to issue a query is using session's query method.

  • The following examples show dynamic queries that do not specify which index to use.
    Please refer to querying an index for other examples.

  • Querying can be enhanced using these extension methods.

Query collection - no filtering

# This is a Full Collection Query
# No auto-index is created since no filtering is applied

all_employees = list(  # Execute the query
    session.query(object_type=Employee)  # Query for all documents from 'Employees' collection
)
# This is a Full Collection Query
# No auto-index is created since no filtering is applied

# Query for all documents from 'Employees' collection
query = session.query(object_type=Employee)

# Execute the query
all_employees = list(query)

# All 'Employee' entities are loaded and will be tracked by the session
// This RQL is a Full Collection Query
// No auto-index is created since no filtering is applied

from "Employees"

Query collection - by ID

# Query collection by document ID
# No auto-index is created when querying only by ID

employee = (
    session.query(object_type=Employee)
    .where_equals("Id", "employees/1-A")  # Query for specific document from 'Employees' collection
    .first()  # Execute the query
)

# The resulting 'Employee' entity is loaded and will be tracked by the session
# Query collection by document ID
# No auto-index is created when querying only by ID

# Query for specific document from 'Employees' collection
query = session.query(object_type=Employee).where_equals("Id", "employees/1-A")

# Execute the query
employee_result = query.first()

# The resulting 'Employee' entity is loaded and will be tracked by the session
// This RQL queries the 'Employees' collection by ID
// No auto-index is created when querying only by ID

from "Employees" where id() == "employees/1-A"

Query collection - with filtering

# Query collection - filter by document field

# An auto-index will be created if there isn't already an existing auto-index
# that indexes this document field

employees = list(  # Execute the query
    session.query(object_type=Employee).where_equals(
        "first_name", "Robert"
    )  # Query for all 'Employee' documents that match this predicate
)

# The resulting 'Employee' entities are loaded and will be tracked by the session
# Query collection - filter by document field

# An auto-index will be created if there isn't already an existing auto-index
# that indexes this document field

# Query for all 'Employee' documents that match this predicate
query = session.query(object_type=Employee).where_equals("first_name", "Robert")

# Execute the query
employees = list(query)

# The resulting 'Employee' entities are loaded and will be tracked by the session
// Query collection - filter by document field

// An auto-index will be created if there isn't already an existing auto-index
// that indexes the requested field

from "Employees" where FirstName == "Robert"

Query collection - with paging

# Query collection - page results
# No auto-index is created since no filtering is applied

products = list()  # Execute the query

# The resulting 'Product' entities are loaded and will be tracked by the session
# Query collection - page results
# No auto-index is created since no filtering is applied

query = (
    session.query(object_type=Product).skip(5).take(10)  # Skip first 5 results
)  # Load up to 10 entities from 'Products' collection

# Execute the query
products = list(query)

# The resulting 'Product' entities are loaded and will be tracked by the session
// Query collection - page results
// No auto-index is created since no filtering is applied

from "Products" limit 5, 10 // skip 5, take 10
  • By default, if the page size is not specified, all matching records will be retrieved from the database.

session.advanced.document_query

Example:

# Query with document_query - filter by document field

# An auto-index will be created if there isn't already an existing auto-index
# that indexes this document field

employees = list(  # Execute the query
    session.advanced.document_query(object_type=Employee).where_equals(  # Use document_query
        "first_name", "Robert"
    )  # Query for all 'Employee' documents that match this predicate
)

# The resulting 'Employee' entities are loaded and will be tracked by the session
// Query collection - filter by document field

// An auto-index will be created if there isn't already an existing auto-index
// that indexes the requested field

from "Employees" where FirstName = "Robert"

session.advanced.raw_query

  • Queries defined with query or document_query are translated by the RavenDB client to RQL
    when sent to the server.

  • The session also gives you a way to express the query directly in RQL using the raw_query method.

Example:

# Query with RawQuery - filter by document field

# An auto-index will be created if there isn't already an existing auto-index
# that indexes this document field

employees = list(  # Execute the query
    session.advanced.raw_query(
        "from 'Employees' where first_name = 'Robert'", object_type=Employee
    )  # Provide RQL to RawQuery
)
# The resulting 'Employee' entities are loaded and will be tracked by the session

Syntax

# Overloads for querying a collection OR an index:
# ================================================

def query(
    self, source: Optional[Query] = None, object_type: Optional[Type[_T]] = None
) -> DocumentQuery[_T]:
    ...

def query_collection(
    self, collection_name: str, object_type: Optional[Type[_T]] = None
) -> DocumentQuery[_T]:
    ...

def query_index(self, index_name: str, object_type: Optional[Type[_T]] = None) -> DocumentQuery[_T]:
    ...

def document_query(
    self,
    index_name: str = None,
    collection_name: str = None,
    object_type: Type[_T] = None,
    is_map_reduce: bool = False,
) -> DocumentQuery[_T]:
    ...

# Overloads for querying an index:
# ================================
def query_index_type(
    self, index_type: Type[_TIndex], object_type: Optional[Type[_T]] = None
) -> DocumentQuery[_T]:
    ...

def document_query_from_index_type(
    self, index_type: Type[_TIndex], object_type: Type[_T]
) -> DocumentQuery[_T]:
    ...

# RawQuery
# ================================
def raw_query(self, query: str, object_type: Optional[Type[_T]] = None) -> RawDocumentQuery[_T]:
    ...
Parameter Type Description
object_type Type[_T] Queried entities type
collection_name str Queried collection name
query str RQL query string
index_name str Queried index name
index_type Type[_TIndex] Queried index type
is_map_reduce bool Is a map-reduce index queried
Return Value
DocumentQuery[_T]
RawDocumentQuery[_T]
Instances exposing additional query methods and extensions