Dadas las siguientes clases:forma más sencilla de aplanar documento en una vista en RavenDB
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
}
que puedo crear un índice que permite cliente para consultar la vista de la siguiente manera:
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
};
}
}
Esto ciertamente funciona y produce el resultado deseado de una vista con los datos transformados a la estructura requerida en la aplicación del cliente. Sin embargo, es muy prolijo, será una pesadilla de mantenimiento y probablemente sea bastante ineficiente con toda la construcción de objetos redundantes.
¿Existe una manera más simple de crear un índice con la estructura requerida (ViewA) dada una colección de documentos (DocA)?
MÁS INFORMACIÓN El problema parece ser que con el fin de tener el índice de contener los datos en la estructura transformada (viewa), tenemos que hacer un Reducir. Parece que una Reducir debe tener tanto un grupo ON y un SELECT con el fin de funcionar como se espera por lo que la siguientes no son válidos:
VÁLIDA REDUCIR Cláusula 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;
Esto produce: Sistema. InvalidOperationException: la selección del inicializador de variables debe tener una expresión lambda con un objeto create expression
Claramente necesitamos tener 'seleccionar nuevo'.
NO VÁLIDA REDUCIR Cláusula 2:
Reduce = results => from result in results
select new ViewA
{
Id = result.Id,
Name = result.Name,
CurrencyName = result.CurrencyName
};
Este prduces: System.InvalidCastException: No se puede convertir objeto de tipo 'ICSharpCode.NRefactory.Ast.IdentifierExpression' al tipo 'ICSharpCode.NRefactory.Ast.InvocationExpression '.
Claramente, también necesitamos tener el 'grupo en nuevo'.
Gracias por cualquier ayuda que pueda proporcionar.
(Nota: la eliminación del tipo (viewa) de las llamadas a constructores no tiene ningún efecto en lo anterior)
ACTUALIZACIÓN CON CORRECTO ENFOQUE
Como se indica en el blog de Daniel se menciona en la respuesta a continuación, aquí es la forma correcta de hacer esto para este ejemplo:
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
};
// Top-level properties on ViewA that match those on DocA
// do not need to be stored in the index.
Store(x => x.CurrencyName, FieldStorage.Yes);
}
}
Gracias @Phill. No sé qué pasó con otra respuesta que estaba aquí ... –