Query Overview


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

    • LINQ - when querying with the session's Query method.
    • Low-level API - when querying with the session's DocumentQuery method.
    • RQL:
      • when querying with the session's RawQuery method.
      • when querying from the Query view in Studio.
  • Queries defined with Query or DocumentQuery 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 by using the session's Query method which supports LINQ.
    Both the LINQ method syntax and the LINQ query syntax are supported.

  • 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

List<Employee> allEmployees = session
    .Query<Employee>() // Query for all documents from 'Employees' collection
    .ToList();         // Execute the query

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

List<Employee> allEmployees = await asyncSession
    .Query<Employee>() // Query for all documents from 'Employees' collection
    .ToListAsync();    // Execute the query

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

// Query for all documents from 'Employees' collection
IRavenQueryable<Employee> query = from employee in session.Query<Employee>()
                                  select employee;
// Execute the query
List<Employee> allEmployees = query.ToList();

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

// Query for all documents from 'Employees' collection
IRavenQueryable<Employee> query = from employee in asyncSession.Query<Employee>()
                                  select employee;
// Execute the query
List<Employee> allEmployees = await query.ToListAsync();

// 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 employee = session
    .Query<Employee>()
    .Where(x => x.Id == "employees/1-A") // Query for specific document from 'Employees' collection 
    .FirstOrDefault();                   // 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

Employee employee = await asyncSession
    .Query<Employee>()
    .Where(x => x.Id == "employees/1-A") // Query for specific document from 'Employees' collection 
    .FirstOrDefaultAsync();              // 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 
IRavenQueryable<Employee> query = from employee in session.Query<Employee>()
                                  where employee.Id == "employees/1-A"
                                  select employee;
// Execute the query
Employee employeeResult = query.FirstOrDefault();

// 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 
IRavenQueryable<Employee> query = from employee in asyncSession.Query<Employee>()
                                  where employee.Id == "employees/1-A"
                                  select employee;
// Execute the query
Employee employeeResult = await query.FirstOrDefaultAsync();

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

List<Employee> employees = session
    .Query<Employee>()
    .Where(x => x.FirstName == "Robert") // Query for all 'Employee' documents that match this predicate 
    .ToList();                           // Execute the 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 this document field

List<Employee> employees = await asyncSession
    .Query<Employee>()
    .Where(x => x.FirstName == "Robert") // Query for all 'Employee' documents that match this predicate 
    .ToListAsync();                      // Execute the 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 this document field

// Query for all 'Employee' documents that match the requested predicate 
IRavenQueryable<Employee> query = from employee in session.Query<Employee>()
                                  where employee.FirstName == "Robert"
                                  select employee;
// Execute the query
List<Employee> employees = query.ToList();

// 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 the requested predicate 
IRavenQueryable<Employee> query = from employee in asyncSession.Query<Employee>()
                                  where employee.FirstName == "Robert"
                                  select employee;
// Execute the query
List<Employee> employees = await query.ToListAsync();

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

List<Product> products = session
    .Query<Product>()
    .Skip(5)   // Skip first 5 results
    .Take(10)  // Load up to 10 entities from 'Products' collection
    .ToList(); // 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

List<Product> products = await asyncSession
    .Query<Product>()
    .Skip(5)        // Skip first 5 results
    .Take(10)       // Load up to 10 entities from 'Products' collection
    .ToListAsync(); // 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

IRavenQueryable<Product> query = (from product in session.Query<Product>()
                                 select product)
                                 .Skip(5)   // Skip first 5 results
                                 .Take(10); // Load up to 10 entities from 'Products' collection
// Execute the query
List<Product> products = query.ToList();

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

IRavenQueryable<Product> query = (from product in asyncSession.Query<Product>()
                                 select product)
                                 .Skip(5)   // Skip first 5 results
                                 .Take(10); // Load up to 10 entities from 'Products' collection
// Execute the query
List<Product> products = await query.ToListAsync();

// 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.DocumentQuery

  • DocumentQuery provides a full spectrum of low-level querying capabilities,
    giving you more flexibility and control when making complex queries.

  • Below is a simple DocumentQuery usage.
    For a full description and more examples see:

Example:

// Query with DocumentQuery - filter by document field

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

List<Employee> employees = session
    .Advanced.DocumentQuery<Employee>()      // Use DocumentQuery
    .WhereEquals(x => x.FirstName, "Robert") // Query for all 'Employee' documents that match this predicate 
    .ToList();                               // Execute the query

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

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

List<Employee> employees = await asyncSession
    .Advanced.AsyncDocumentQuery<Employee>() // Use DocumentQuery
    .WhereEquals(x => x.FirstName, "Robert") // Query for all 'Employee' documents that match this predicate 
    .ToListAsync();                          // Execute the 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"

Session.Advanced.RawQuery

  • Queries defined with Query or DocumentQuery 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 RawQuery 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

List<Employee> employees = session
     // Provide RQL to RawQuery
    .Advanced.RawQuery<Employee>("from 'Employees' where FirstName = 'Robert'")
     // Execute the query
    .ToList();

// The resulting 'Employee' entities are loaded and will be tracked by the session 
// 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

List<Employee> employees = await asyncSession
     // Provide RQL to AsyncRawQuery
    .Advanced.AsyncRawQuery<Employee>("from 'Employees' where FirstName = 'Robert'")
     // Execute the query
    .ToListAsync();

// The resulting 'Employee' entities are loaded and will be tracked by the session 

Custom methods and extensions for LINQ

Available custom methods and extensions for the session's Query method:

Syntax

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

IRavenQueryable<T> Query<T>(string indexName = null, 
    string collectionName = null, bool isMapReduce = false);

IDocumentQuery<T> DocumentQuery<T>(string indexName = null,
    string collectionName = null, bool isMapReduce = false);

// Overloads for querying an index:
// ================================

IRavenQueryable<T> Query<T, TIndexCreator>();

IDocumentQuery<T> DocumentQuery<T, TIndexCreator>();

// RawQuery:
// =========

IRawDocumentQuery<T> RawQuery<T>(string query);
Parameter Type Description
T object
  • The type of entities queried
TIndexCreator string
  • The index class type
collectionName string
  • Name of a collection to query
  • No need to provide this param when specifying T
  • Specify the collection name when querying a collection that is created
    on the fly, i.e. when querying Artifical Documents
  • Mutually exclusive with indexName
indexName string
  • Name of index to query
  • Mutually exclusive with collectionName
isMapReduce string
  • Whether querying a map-reduce index
query string
  • The RQL query string
Return Value
IRavenQueryable
IDocumentQuery
IRawDocumentQuery
Instances exposing additional query methods and extensions