Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 5,953 | Comments: 44,410

filter by tags archive

Rob’s SprintResult Transformers

By far the most confusing feature in RavenDB has been the index’s Transform Result. We introduced this feature to give the user the ability to do server side projections, including getting data from other documents.

Unfortunately, when we introduced this feature, we naturally added it to the index, and that cause a whole lot of confusion. In particular, people seemed to have a very hard time distinguishing between what get indexed and is searchable and the output of the index. To make matters worse, we also had major issues with how to determine the input of the TransformResults function. In short, the entire thing works, but from the point of view of an external user, that is really something that is very finicky and hard to get.

Instead, during Rob’s sprint, we have introduced a totally new concept. Stand-alone Result Transformers.

Here is what they look like:

public class OrdersStatsTransfromer : AbstractTransformerCreationTask<Order>
    public OrdersStatsTransfromer()
        TransformResults = orders =>
                           from order in orders
                           select new
                               CustomerName = LoadDocument<Customer>(order.CustomerId).Name,
                               LinesCount = order.Lines.Count

And yes, they are quite intentionally modeled to be very similar to the way you would define them up to now, but outside of the index.

Now, why is that important? Because now you can apply a Transform Results on the server side without being tied to a customer.

For example, let us see how we can make use of this new feature:

var customerOrders = session.Query<Order>()
    .Where(x => x.CustomerId == "customers/123")
    .TransformWith<OrdersStatsTransfromer, OrderViewModel>()

This separation between the result transformer and the index means that we can apply it to things like automatic indexes as well.

In fact, we can apply it during load:

var ovm = session.Load<OrdersStatsTransfromer, OrderViewModel>("orders/1");

There are a whole bunch of other goodies in there, as well. We made sure that now you don’t have to worry about the inputs to the transform. We will automatically use the right values when you access them, based on whatever you stored the field in the index or if it is accessible on the document.

All in all, this is a very major step forward, and it makes it drastically easier to use Result Transformers in various ways.

More posts in "Rob&rsquo;s Sprint" series:

  1. (08 Mar 2013) The cost of getting data from LevelDB
  2. (07 Mar 2013) Result Transformers
  3. (06 Mar 2013) Query optimizer jumped a grade
  4. (05 Mar 2013) Faster index creation
  5. (04 Mar 2013) Indexes and the death of temporary indexes
  6. (28 Feb 2013) Idly indexing


Johannes Rudolph

Does that mean TranformResults on idexes will be deprecated? Whats the cost of an index result transform vs these new standalone result tranforms? I thought (but may be wrong) that TransformResults as part of an index is materialized, so it's blazingly fast.

Also, when in general would you advice using ResultTransformers vs. Loading a related document via .Include and the projecting viewmodels on the client?

Matt Warren


No the existing TR aren't materialised, they are only applied at query time. The new TR will work in the same way, but they difference is that they are de-coupled from an index, i.e they can be re-used by different indexes, you can use the same index with/without a TR etc.

To materialise you need to use Store in the index. That puts the fields into the index where they can be fetched from, rather than having to go an get the entire doc from the doc store. See "Field Options" on http://ravendb.net/docs/client-api/querying/static-indexes/configuring-index-options

With regards to TR v Loading and Include, it makes most sense to use a TR if you want to cut-down on network bandwidth. Loading via Include will pull back entire docs

Sean Feldman

Is this in v2.0? http://ravendb.net/docs/2.0/ doesn't mention this...

Ayende Rahien

Johanne, Yes, we are deprecating the TransformResults. And there is NO perf difference between the two. Both of those happened at query time, not at indexing time. And doing projections on the client side is only useful if you need the entire document. If you want to get just some of the data out, it is probably easier with result transformer.

Ayende Rahien

Sean, This is a 2.5 feature.

Barry Hagan

This is really nice and clean. Especially on the Load<TR, T> calls to get a partial document directly from the database - I think a lot of people have been looking for that one.


and what if you wish to populate properties on a reduce result at query time? how can this be done with one round trip to the database

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
  2. Special Offer (2):
    27 May 2015 - 29% discount for all our products
  3. RavenDB Sharding (3):
    22 May 2015 - Adding a new shard to an existing cluster, splitting the shard
  4. Challenge (45):
    28 Apr 2015 - What is the meaning of this change?
  5. Interview question (2):
    30 Mar 2015 - fix the index
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats