Querying RavenDB databases
Monday 17 December 2012
As we have seen in previous blog posts getting data from a RavenDB database is easy. Either use the IDocumentSession.Query<T>() function to load a series of documents or the IDocumentSession..Load<T>() function to load a document using its identity. However sometimes we want more control over what we want to load. It turns out this is rather easy as the IDocumentSession.Query<T>() function returns an IQueryable<T>, actually it returns a IRavenQueryable<T> to be exact but more about that another time.
Querying the database
As IDocumentSession.Query<T>() return an IQueryable<T> we can just start composing queries just as we can with EntityFramework or another ORM. In my original online example you might have noticed that the books aren't ordered. As with any query this is easy to correct. All we need to do is add an order by clause.
If you prefer the full LINQ syntax that is no problem as it produced exactly the same result±
In this case I am only ordering the result set but you can also use other operators if you like. Just want books from an author starting with “A”? No problem, just add the filter and it works. The following view search for books where the title or author starts with the passed string.
If you try this you might notice one big difference from EntityFramework or in memory LINQ queries. If you search for books starting with a lowercase “the” both “The Hitchhiker's Guide to the Galaxy” and “The RavenDB Book” are returned. And in the query I am not doing anything about making this a case insensitive search. It turns out RavenDB does so by default as it uses Lucene.Net to create indexes. As we didn’t create any indexes you might be wondering where this comes from. It turns out that RavenDB always uses an index when you do a query. You can explicitly create them if you want to. However if you do not, as is the case here, RavenDB will try to find a matching index or create a temporary index if a marching one isn’t found. If the same temporary index is used frequently RavenDB will automatically promote it to a permanent index. That might sound like a bad idea, after all in SQL Server index help with querying but can also slow updates down. In RavenDB this isn’t the case as indexes are update asynchronously so we get the query benefits without the update penalties. Of course there is no such thing as a free lunch and in the case of RavenDB this can mean we use a stale index for the query. That might sounds bad but isn’t quite as bad as it sounds as the data is never stale, just the index, and we can easily control when we want to wait for a non stale index.
Want to try? I have this example running on Windows Azure here.