RavenDB Indexes While Developing

 
event

At work, my team and I have been working with RavenDB for quite some time.

Despite some people objections, the team usually shares a single development database. There is still the occasional “I made this breaking change… Guys! Get latest!!” but happens quite rarely.

Besides documents, there is another data artifact that is very necessary for RavenDB to work: indexes (and transformers). Favoring explicit indexes (instead of automatically created ones) means we end up with bunch of indexes defined in code.

From Code to Database

RavenDB offers the IndexCreator high-level api to easily create indexes. Question is: when will that code that creates data indexes from their code definitions executed?

When application starts

An strategy we have followed in the past was placing index creation code right after the DocumentStore initialization code. Since that initialization is recommended to occur once per application, we ended up re-creating the indexes every time the app starts.

An app in development re-starts many times and the problem that I pointed out in the first paragraph (developers that do not have the latest version of the code running) worsens seriously: an application with the outdated index definition will override the just-updated index.

So, all in all, that approach was not such a good idea at all.

On demand

Currently we use a small console program (or LINQPad script) that updates the indexes when needed.
Such approach can even be used to automatically deploy index definitions from environment to environment (given we have access to that environment database, of course).

The multiple database challenge

What happens when multiple databases are accessed in the application? Out-of-the box, the simpler to use IndexCreator.CreateIndexes() takes an assembly, which means that if all indexes for all databases live in the same assembly (and we tend to favor single –or few– assembly solutions), all the databases will contain all assembly definitions.

Not all databases contain the same collections, so some indexes are empty (consuming little to no resources); and transformers won’t be used in queries against that database. But having artifacts that should not be there is still a small annoyance.

OSS to the Rescue

To solve this, and some other problems, rvn-izer has been created.

Rvn.Izr_Nuget

Installing the Nuget package in the project that contains the indexes, gives access to the CreateInAttribute that can be used to decorate indexes and transformers with the name of the database they correspond.

Filter by database name

Using the Indexes fluent interface, we can get the ExportProvider instance that contains the artifacts corresponding to the specified database and invoke the corresponding IndexCreator.CreateIndexes() overload to stop creating artifacts where they do not belong.

Safety first

Another interesting feature Indexes offers is the ability to return artifacts not decorated with the attribute. That opens the chance to create an automated test that verifies, for instance, that we are not forgetting to decorate a given artifact and, thus, not creating it.

Useful?

Play with it, use and abuse it and, if you fancy more features, PR your way through.