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

Phi*_*rdt 5 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
}
Run Code Online (Sandbox Code Playgroud)

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

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
                      };
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

无效减少条款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;
Run Code Online (Sandbox Code Playgroud)

这会产生:System.InvalidOperationException:变量初始值设定项select必须具有带对象create expression的lambda表达式

显然,我们需要'选择新'.

无效减少条款2:

        Reduce = results => from result in results
                      select new ViewA
                      {
                          Id = result.Id,
                          Name = result.Name,
                          CurrencyName = result.CurrencyName
                      };
Run Code Online (Sandbox Code Playgroud)

这个产生: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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*rdt 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);
    }
}
Run Code Online (Sandbox Code Playgroud)