Joining documents in RavenDB 2.0

One of the main differences between relational databases and document databases is the lack of native joining capabilities, right? This is no longer true for RavenDB. Yes, we already had very effective ways to deal with document relations before, but now in RavenDB 2.0 we can do much better.

Let’s say our model looks like this:

image

In order to display a list of posts, we need the title, the author’s name and the content. So we effectively need to join posts with their authors. This is what we want:

image

If you don’t know how to do this in RavenDB 1.0, please go to this post.

In RavenDB 2.0 however, there is a new feature that let’s us load documents during indexing time. This means, we can load the related author document while we index the post document. Combine this features with the possibility to use an index as the read-store for your queries…

Here’s how our index looks like:

image

Note how we first load the author document and then store the author’s name inside our index, so we can get that value back at query time.

Here’s how a query looks like:

image

How awesome is that?

Please note that RavenDB does not load the author document at query time. Instead, it already has the author’s name stored in the index, so querying is as ultra-fast as if there wasn’t any relation at all.

If the author’s name changes, RavenDB will automatically recompute the index for all the posts that are related with that author. Unlike with denormalized references, we don’t need to maintain that relation!

Personally, I think this will fundamentally change how we work with RavenDB. Do you agree?

12 Responses to Joining documents in RavenDB 2.0

  1. Matthias Zeis January 4, 2013 at 6:30 am #

    That’s a nice feature indeed.

  2. Sean Kearon January 4, 2013 at 11:31 am #

    I agree totally – making linking documents much, much easier like this is a huge step for RavenDB. I think it’s my absolute favourite feature of 2.0!

  3. Owen January 11, 2013 at 3:24 am #

    What will happen during indexing if the referenced document does not exist?

    • Daniel Lang January 11, 2013 at 5:07 am #

      RavenDB is smart about that and won’t crash – it will insert ‘null’ as the AuthorName.

  4. Vindberg February 13, 2013 at 2:24 pm #

    Is it required to specify “Title” and “Content” as FieldIndexing.Analyzed? Isn’t it that by default?

    Thanks for a great post btw. This is golden.

    • Daniel Lang February 13, 2013 at 2:32 pm #

      If you don’t mark them as Analyzed they will be stored using the DefaultAnalyzer which doesn’t allow full text search. If you want FTS, you probably the StandardAnalyzer (!=DefaultAnalyzer) which is set automatically if you mark a field as analyzed as I did. Please see my other posts of searching for more details on this.

  5. Vindberg February 14, 2013 at 8:24 am #

    Ohh yes, I can see that in the Studio also. Thanks.

  6. Vindberg February 18, 2013 at 1:20 pm #

    Hi again, using this example how would you suggest getting Id of the Post in the list? In Raven Studio I can see that an autogenerated id named __document_Id is available. I have tried adding it specifically in the index “PostId” but it is not returned when I query the list?

    • Daniel Lang February 18, 2013 at 1:38 pm #

      Yes, that works – you can add a field “PostId” to your index. In order to be able to query it, you have to mark the field as stored. Please use the Store() method from the example above for this.

  7. afif June 1, 2013 at 5:00 am #

    What if you wish to filter by author name? you’ll need to query for PostProjections instead of Posts. The AsProjection() you have appended to the query becomes redundant then. Would this work?

    Also what is the difference between As() and AsProjection() ?

  8. Sean Kearon October 17, 2013 at 7:27 am #

    Daniel – how does this compare to Result Transformers?

    http://ravendb.net/docs/2.5/client-api/querying/results-transformation/result-transformers?version=2.5

    On first glance, I’d say that the Result Transformer performs the transformation at load time from the document store. Whereas ProjectFromIndexFieldsInto and AsProjection work from the index fields.

    Is that it?

  9. Sean Kearon October 17, 2013 at 7:39 am #

    I think I’ve just answered my own question. The venerable Mr Ashton says that Raven is clever enough to load from the index if the value is there:

    http://codeofrob.com/entries/ravendb—avoiding-ambiguity-in-result-transformers.html

Leave a Reply