Querying an Index
-
Prior to reading this article, it is recommended to take a look at the Query Overview.
-
For a basic indexes overview, see the Indexes Overview.
-
Indexing the content of your documents allows for fast document retrieval when querying the index.
-
This article is a basic overview of how to query a static index using code.
- For dynamic query examples see Query Overview.
- An index can also be queried from Studio using RQL.
-
In this page:
- Query an index by
Query
(using LINQ) - Query an index by
DocumentQuery
(low-level API) - Query an index by
RawQuery
(using RQL)
- Query an index by
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 theIndexEntry
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"