Indexes: Indexing Basics

To achieve very fast response times, RavenDB handles indexing in the background whenever data is added or changed. This approach allows the server to respond quickly even when large amounts of data have changed. The only drawback of this choice is that results might be stale (more about staleness in next section). Underneath, the server is using Lucene to perform indexation and Raven Query Language for querying.

Stale Indexes

The notion of stale indexes comes from an observation deep in RavenDB's design, assuming that the user should never suffer from assigning the server big tasks. As far as RavenDB is concerned, it is better to be stale than offline, and as such it will return results to queries even if it knows they may not be as up-to-date as possible.

RavenDB returns quickly for every client request, even if involves re-indexing hundreds of thousands of documents. Since the previous request has returned so quickly, the next query can be made a millisecond after that. and results will be returned but they will be marked as Stale.

Information

You can read more about stale indexes here.

Querying

RavenDB uses Raven Query Language (RQL), an SQL-like querying language for querying. The easiest way for us would be to expose a method in which you could pass your RQL-flavored query as a string (we did that) and do not bother about anything else.

The fact is that we did not stop at this point. We went much further by exposing LINQ-based querying with strong-type support that hides all Lucene syntax complexity:

List<Employee> employees = session
    .Query<Employee>("Employees/ByFirstName")
    .Where(x => x.FirstName == "Robert")
    .ToList();
IQueryable<Employee> employees =
    from employee in session.Query<Employee>("Employees/ByFirstName")
    where employee.FirstName == "Robert"
    select employee;
from index 'Employees/ByFirstName'
where FirstName = 'Robert'

You can also create queries manually by using DocumentQuery or RawQuery, both available as a part of advanced session operations:

List<Employee> employees = session
    .Advanced
    .DocumentQuery<Employee>("Employees/ByFirstName")
    .WhereEquals(x => x.FirstName, "Robert")
    .ToList();
List<Employee> employees = session
    .Advanced
    .RawQuery<Employee>("from index 'Employees/ByFirstName' where FirstName = 'Robert'")
    .ToList();
from index 'Employees/ByFirstName'
where FirstName = 'Robert'

Types of Indexes

You probably know that indexes can be divided by their source of origin to the static and auto indexes (if not, read about it here), but a more interesting division is by functionality. For this case we have Map and Map-Reduce indexes.

Map indexes (sometimes referred as simple indexes) contain one (or more) mapping functions that indicate which fields from documents should be indexed. They indicate which documents can be searched by which fields.

Map-Reduce indexes allow complex aggregations to be performed in a two-step process. First by selecting appropriate records (using the Map function), then by applying a specified reduce function to these records to produce a smaller set of results.

Map Indexes

You can read more about Map indexes here.

Map-Reduce Indexes

More detailed information about Map-Reduce indexes can be found here.