We have recently introduced the basic concepts about indexing in RavenDB. We left without saying nothing about the options we, as developers, have to manage indexes:

  • Manually via the RavenDB Studio;
  • Programmatically directly within the application;

Index overview

If we take a look at the Indexes tab in the Studio and we edit one of the indexes we can see something that we, as .net developers, are really familiar with: linq.

image

An index is defined using a linq expression, wow, but as we may suspect the server has no knowledge at all of what a linq expression is, what we see in the index editor is basically text, familiar to us, but text that the server can understand and use to “run” the index.

Manual index management

So…as we can imagine we can use the Studio to create and manage indexes, creating a new index is just a matter of defining the correct lambda expression that defines what we want to index, basically nothing more.

As we can imagine as the index complexity grows the manual management can become cumbersome.

Programmatic index management

The following map/reduce index is a good starting point:

image

it is still a fairly simple index (a sort of tag cloud) but is a good sample of the manual management complexity we can achieve quickly. The above index can be fully managed by code:

public class Genres_Count : AbstractIndexCreationTask<Album, Genres_Count.GenresCloud>
{
public class GenresCloud
{
public string Id { get; set; }
public string Name { get; set; }
public int Count { get; set; }
}

public Genres_Count()
{
this.Map = albums => from album in albums
select new
{
Id = album.Genre.Id,
Name = album.Genre.Name,
Count = 1
};

this.Reduce = results => from genreCount in results
group genreCount by genreCount.Id into g
select new
{
Id = g.Key,
Name = g.First().Name,
Count = g.Sum( x => x.Count )
};

this.IndexSortOptions.Add( i => i.Count, Raven.Abstractions.Indexing.SortOptions.Int );
}
}

The above C# code is exactly equal to the index we have seen in the studio, in fact the index in the studio has been generated at application startup time using the following one line of code:

//ds is an instance of IDocumentStore
IndexCreation.CreateIndexes( Assembly.GetExecutingAssembly(), ds );

We have defined in a single class, inheriting from the RavenDB AbstractIndexCreationTask<TDocument, TReduceResult>:

  1. the name of the index, the convention is that My_Sample_Index is translated by the server into a index named My/Sample/Index;
  2. The map logic;
  3. The reduce logic;
  4. Some index options;
  5. And the shape of the reduce result;

Having a strongly typed index definition allows us to write some strongly typed C# code to use it:

var cloud = await Task.Factory.StartNew<IEnumerable<Genres_Count.GenresCloud>>( () =>
{
using( var session = this.documentStore.OpenSession() )
{
var data = session.Query<Genres_Count.GenresCloud, Genres_Count>()
.OrderByDescending( c => c.Count );

return data;
}
} );

.m