在RavenDB中将文档展平到视图的最简单方法

时间:2012-03-27 10:59:20

标签: c# 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
}

我可以创建一个允许客户端查询视图的索引,如下所示:

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
                      };
    }
}

这肯定有效并产生所需的视图结果,数据转换为客户端应用程序所需的结构。然而,它是不可行的冗长,将是一个维护噩梦,并且可能在所有冗余对象构造中效率相当低。

在给定文档集合(DocA)的情况下,是否有更简单的方法创建具有所需结构的索引(ViewA)?

更多信息 问题似乎是为了让索引保存转换结构(ViewA)中的数据,我们必须进行Reduce。似乎Reduce必须同时具有GROUP ON和SELECT才能按预期工作,因此以下内容无效:

INVALID REDUCE CLUUSE 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;

这会产生:System.InvalidOperationException:变量初始化程序选择必须具有带对象创建表达式的lambda表达式

显然我们需要'选择新'。

INVALID REDUCE CLAUSE 2:

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

此产品:System.InvalidCastException:无法将类型为“ICSharpCode.NRefactory.Ast.IdentifierExpression”的对象强制转换为“ICSharpCode.NRefactory.Ast.InvocationExpression”。

显然,我们还需要'新组'。

感谢您提供的任何帮助。

(注意:从构造函数调用中删除类型(ViewA)对上面的内容没有影响)

使用正确的方法更新

如下面答案中提到的Daniel的博客中所述,以下是此示例的正确方法:

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);
    }
}

1 个答案:

答案 0 :(得分:4)

一种解决方案,只需在Map中展平并配置索引以仅存储DocA中不存在的属性。

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);
    }
}