Querying an Index




Query an index by Query

  • In the following examples we query an index using the session's Session.Query method, which supports LINQ.

  • Querying can be enhanced using these extension methods.


Query index - no filtering:

// Query the 'Employees' collection using the index - without filtering
// (Open the 'Index' tab to view the index class definition)

List<Employee> employees = session
     // Pass the queried collection as the first generic parameter
     // Pass the index class as the second generic parameter
    .Query<Employee, Employees_ByName>()
     // Execute the query
    .ToList();

// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
// Query the 'Employees' collection using the index - without filtering

List<Employee> employees = await asyncSession
     // Pass the queried collection as the first generic parameter
     // Pass the index class as the second generic parameter
    .Query<Employee, Employees_ByName>()
     // Execute the query
    .ToListAsync();

// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
// Query the 'Employees' collection using the index - without filtering

List<Employee> employees = session
     // Pass the index name as a parameter
     // Use slash `/` in the index name, replacing the underscore `_` from the index class definition
    .Query<Employee>("Employees/ByName")
     // Execute the query
    .ToList();

// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned
// The index definition:

public class Employees_ByName : AbstractIndexCreationTask<Employee, Employees_ByName.IndexEntry>
{
    // The IndexEntry class defines the index-fields
    public class IndexEntry
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
        
    public Employees_ByName()
    {
        // The 'Map' function defines the content of the INDEX-fields
        Map = employees => from employee in employees
            select new IndexEntry
            {
                // * The content of INDEX-fields 'FirstName' & 'LastName'
                //   is composed of the relevant DOCUMENT-fields.
                FirstName = employee.FirstName,
                LastName = employee.LastName
                
                // * The index-fields can be queried on to fetch matching documents. 
                //   You can query and filter Employee documents based on their first or last names.
                
                // * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
                //   will Not be indexed.
                
                // * Note: the INDEX-field name does Not have to be exactly the same
                //   as the DOCUMENT-field name. 
            };
    }
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition

from index "Employees/ByName"

// All 'Employee' documents that contain DOCUMENT-fields 'FirstName' and\or 'LastName' will be returned

Query index - with filtering:

// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = session
     // Pass the IndexEntry class as the first generic parameter
     // Pass the index class as the second generic parameter
    .Query<Employees_ByName.IndexEntry, Employees_ByName>()
     // Filter the retrieved documents by some predicate on an INDEX-field
    .Where(x => x.LastName == "King")
     // Specify the type of the returned document entities
    .OfType<Employee>()
     // Execute the query
    .ToList();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = await asyncSession
     // Pass the IndexEntry class as the first generic parameter
     // Pass the index class as the second generic parameter
    .Query<Employees_ByName.IndexEntry, Employees_ByName>()
     // Filter the retrieved documents by some predicate on an INDEX-field
    .Where(x => x.LastName == "King")
     // Specify the type of the returned document entities
    .OfType<Employee>()
     // Execute the query
    .ToListAsync();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The index definition:

public class Employees_ByName : AbstractIndexCreationTask<Employee, Employees_ByName.IndexEntry>
{
    // The IndexEntry class defines the index-fields
    public class IndexEntry
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
        
    public Employees_ByName()
    {
        // The 'Map' function defines the content of the INDEX-fields
        Map = employees => from employee in employees
            select new IndexEntry
            {
                // * The content of INDEX-fields 'FirstName' & 'LastName'
                //   is composed of the relevant DOCUMENT-fields.
                FirstName = employee.FirstName,
                LastName = employee.LastName
                
                // * The index-fields can be queried on to fetch matching documents. 
                //   You can query and filter Employee documents based on their first or last names.
                
                // * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
                //   will Not be indexed.
                
                // * Note: the INDEX-field name does Not have to be exactly the same
                //   as the DOCUMENT-field name. 
            };
    }
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition

from index "Employees/ByName"
where LastName == "King"

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
  • OfType is used to convert the type being used in the where clause (IndexEntry)
    to the collection type (Employee).
    The reason for this is that while the IndexEntry type allows for a strongly typed query,
    the server returns the actual documents entities objects.

  • An exception will be thrown when filtering by fields that are Not defined in the index.

  • Read more about filtering here.


Query index - with paging:

// Query the 'Employees' collection using the index - page results

// This example is based on the previous filtering example
List<Employee> employees = session
    .Query<Employees_ByName.IndexEntry, Employees_ByName>()
    .Where(x => x.LastName == "King")
    .Skip(5)  // Skip first 5 results
    .Take(10) // Retrieve up to 10 documents
    .OfType<Employee>()
    .ToList();

// Results will include up to 10 matching documents
// Query the 'Employees' collection using the index - page results

// This example is based on the previous filtering example
List<Employee> employees = await asyncSession
    .Query<Employees_ByName.IndexEntry, Employees_ByName>()
    .Where(x => x.LastName == "King")
    .Skip(5)  // Skip first 5 results
    .Take(10) // Retrieve up to 10 documents
    .OfType<Employee>()
    .ToListAsync();

// Results will include up to 10 matching documents
// The index definition:

public class Employees_ByName : AbstractIndexCreationTask<Employee, Employees_ByName.IndexEntry>
{
    // The IndexEntry class defines the index-fields
    public class IndexEntry
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
        
    public Employees_ByName()
    {
        // The 'Map' function defines the content of the INDEX-fields
        Map = employees => from employee in employees
            select new IndexEntry
            {
                // * The content of INDEX-fields 'FirstName' & 'LastName'
                //   is composed of the relevant DOCUMENT-fields.
                FirstName = employee.FirstName,
                LastName = employee.LastName
                
                // * The index-fields can be queried on to fetch matching documents. 
                //   You can query and filter Employee documents based on their first or last names.
                
                // * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
                //   will Not be indexed.
                
                // * Note: the INDEX-field name does Not have to be exactly the same
                //   as the DOCUMENT-field name. 
            };
    }
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition

from index "Employees/ByName"
where LastName == "King"
limit 5, 10 // skip 5, take 10
  • Read more about paging here.

Query an index by DocumentQuery

  • Session.Advanced.DocumentQuery provides low-level access to RavenDB's querying mechanism,
    giving you more flexibility and control when making complex queries.

  • For more information about DocumentQuery see:

Example:

// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = session.Advanced
     // Pass the IndexEntry class as the first generic parameter
     // Pass the index class as the second generic parameter
    .DocumentQuery<Employees_ByName.IndexEntry, Employees_ByName>()
     // Filter the retrieved documents by some predicate on an INDEX-field
    .WhereEquals(x => x.LastName, "King")
     // Specify the type of the returned document entities
    .OfType<Employee>()
     // Execute the query
    .ToList();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = await asyncSession.Advanced
     // Pass the IndexEntry class as the first generic parameter
     // Pass the index class as the second generic parameter
    .AsyncDocumentQuery<Employees_ByName.IndexEntry, Employees_ByName>()
     // Filter the retrieved documents by some predicate on an INDEX-field
    .WhereEquals(x => x.LastName, "King")
     // Specify the type of the returned document entities
    .OfType<Employee>()
     // Execute the query
    .ToListAsync();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = session.Advanced
     // Pass the IndexEntry class as the generic param
     // Pass the index name as the param
     // Use slash `/` in the index name, replacing the underscore `_` from the index class definition
    .DocumentQuery<Employees_ByName.IndexEntry>("Employees/ByName")
     // Filter the retrieved documents by some predicate on an INDEX-field
    .WhereEquals(x => x.LastName, "King")
     // Specify the type of the returned document entities
    .OfType<Employee>()
     // Execute the query
    .ToList();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query the 'Employees' collection using the index - filter by INDEX-field

List<Employee> employees = await asyncSession.Advanced
    // Pass the IndexEntry class as the generic parameter
    // Pass the index name as the parameter
    // Use slash `/` in the index name, replacing the underscore `_` from the index class definition
    .AsyncDocumentQuery<Employees_ByName.IndexEntry>("Employees/ByName")
    // Filter the retrieved documents by some predicate on an INDEX-field
    .WhereEquals(x => x.LastName, "King")
    // Specify the type of the returned document entities
    .OfType<Employee>()
    // Execute the query
    .ToListAsync();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The index definition:

public class Employees_ByName : AbstractIndexCreationTask<Employee, Employees_ByName.IndexEntry>
{
    // The IndexEntry class defines the index-fields
    public class IndexEntry
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
        
    public Employees_ByName()
    {
        // The 'Map' function defines the content of the INDEX-fields
        Map = employees => from employee in employees
            select new IndexEntry
            {
                // * The content of INDEX-fields 'FirstName' & 'LastName'
                //   is composed of the relevant DOCUMENT-fields.
                FirstName = employee.FirstName,
                LastName = employee.LastName
                
                // * The index-fields can be queried on to fetch matching documents. 
                //   You can query and filter Employee documents based on their first or last names.
                
                // * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
                //   will Not be indexed.
                
                // * Note: the INDEX-field name does Not have to be exactly the same
                //   as the DOCUMENT-field name. 
            };
    }
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition

from index "Employees/ByName"
where LastName == "King"

Query an index by 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 Session.Advanced.RawQuery method.

Example:

// Query with RawQuery - filter by INDEX-field

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

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// Query with RawQuery - filter by INDEX-field

List<Employee> employees = await asyncSession.Advanced
     // Provide RQL to RawQuery
    .AsyncRawQuery<Employee>("from index 'Employees/ByName' where LastName == 'King'")
     // Execute the query
    .ToListAsync();

// Results will include all documents from 'Employees' collection whose 'LastName' equals to 'King'.
// The index definition:

public class Employees_ByName : AbstractIndexCreationTask<Employee, Employees_ByName.IndexEntry>
{
    // The IndexEntry class defines the index-fields
    public class IndexEntry
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
        
    public Employees_ByName()
    {
        // The 'Map' function defines the content of the INDEX-fields
        Map = employees => from employee in employees
            select new IndexEntry
            {
                // * The content of INDEX-fields 'FirstName' & 'LastName'
                //   is composed of the relevant DOCUMENT-fields.
                FirstName = employee.FirstName,
                LastName = employee.LastName
                
                // * The index-fields can be queried on to fetch matching documents. 
                //   You can query and filter Employee documents based on their first or last names.
                
                // * Employee documents that do Not contain both 'FirstName' and 'LastName' fields
                //   will Not be indexed.
                
                // * Note: the INDEX-field name does Not have to be exactly the same
                //   as the DOCUMENT-field name. 
            };
    }
}
// Note:
// Use slash `/` in the index name, replacing the underscore `_` from the index class definition

from index "Employees/ByName"
where LastName == "King"