Simplest way to flatten document to a view in RavenDB

Posted by degorolls on Stack Overflow See other posts from Stack Overflow or by degorolls
Published on 2012-03-27T10:59:19Z Indexed on 2012/03/27 11:29 UTC
Read the original article Hit count: 247

Filed under:
|

Given the following classes:

public class Lookup
{
    public string Code { get; set; }
    public string Name { get; set; }
}

public class DocA
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Lookup Currency { get; set; }
}

public class ViewA // Simply a flattened version of the doc
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string CurrencyName { get; set; } // View just gets the name of the currency
}

I can create an index that allows client to query the view as follows:

public class A_View : AbstractIndexCreationTask<DocA, ViewA>
{
    public A_View()
    {
        Map = docs => from doc in docs
                      select new ViewA
                      {
                          Id = doc.Id,
                          Name = doc.Name,
                          CurrencyName = doc.Currency.Name
                      };

        Reduce = results => from result in results
                      group on new ViewA
                      {
                          Id = result.Id,
                          Name = result.Name,
                          CurrencyName = result.CurrencyName
                      } into g
                      select new ViewA
                      {
                          Id = g.Key.Id,
                          Name = g.Key.Name,
                          CurrencyName = g.Key.CurrencyName
                      };
    }
}

This certainly works and produces the desired result of a view with the data transformed to the structure required at the client application. However, it is unworkably verbose, will be a maintenance nightmare and is probably fairly inefficient with all the redundant object construction.

Is there a simpler way of creating an index with the required structure (ViewA) given a collection of documents (DocA)?

FURTHER INFORMATION The issue appears to be that in order to have the index hold the data in the transformed structure (ViewA), we have to do a Reduce. It appears that a Reduce must have both a GROUP ON and a SELECT in order to work as expected so the following are not valid:

INVALID REDUCE CLAUSE 1:

        Reduce = results => from result in results
                      group on new ViewA
                      {
                          Id = result.Id,
                          Name = result.Name,
                          CurrencyName = result.CurrencyName
                      } into g
                      select g.Key;

This produces: System.InvalidOperationException: Variable initializer select must have a lambda expression with an object create expression

Clearly we need to have the 'select new'.

INVALID REDUCE CLAUSE 2:

        Reduce = results => from result in results
                      select new ViewA
                      {
                          Id = result.Id,
                          Name = result.Name,
                          CurrencyName = result.CurrencyName
                      };

This prduces: System.InvalidCastException: Unable to cast object of type 'ICSharpCode.NRefactory.Ast.IdentifierExpression' to type 'ICSharpCode.NRefactory.Ast.InvocationExpression'.

Clearly, we also need to have the 'group on new'.

Thanks for any assistance you can provide.

(Note: removing the type (ViewA) from the constructor calls has no effect on the above)

© Stack Overflow or respective owner

Related posts about c#

Related posts about ravendb