鉴于以下课程:
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)
一种解决方案是简单地在 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)