我有一个类似如下的文档结构:
Employer => Positions => RequiredSkills
雇主有一个职位
定位集合有一个RequiredSkill集合.
所需技能包括技能(字符串)和熟练程度(枚举).
如果我使用动态索引,它似乎返回公司,但我想使用索引来填充MVC视图模型以返回到UI.
我是Raven的新手,所以我为做任何愚蠢/不必要的事而道歉!
我有以下映射:
public class PositionSearch : AbstractIndexCreationTask<Employer>
{
public PositionSearch()
{
Map = employers =>
from employer in employers
from position in employer.Positions
select new
{
EmployerId = employer.Id,
EmployerName = employer.Name,
PositionId = position.Id,
PositionTitle = position.Title,
position.Location,
position.Description,
RequiredSkills = position.RequiredSkills
};
StoreAllFields(FieldStorage.Yes);
Index("RequiredSkills_Skill", FieldIndexing.Analyzed);
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试执行以下查询时:
var results = session.Query<PositionSearchResultModel, PositionSearch>()
.Customize(x => x.WaitForNonStaleResults())
.Where(x=>x.RequiredSkills.Any(y=>y.Skill == "SkillName"))
.ProjectFromIndexFieldsInto<PositionSearchResultModel>()
.ToList();
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
System.ArgumentException:
The field 'RequiredSkills_Skill' is not indexed,
cannot query on fields that are not indexed
Run Code Online (Sandbox Code Playgroud)
任何人都可以看到我做错了或为我建议另一种方法吗?
谢谢,
詹姆士
更新我的视图模型 - 谢谢:
public class PositionSearchResultModel
{
public PositionSearchResultModel()
{
RequiredSkills = new HashSet<SkillProficiency>();
}
public string EmployerId { get; set; }
public string EmployerName { get; set; }
public string PositionId { get; set; }
public string PositionTitle { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public ICollection<SkillProficiency> RequiredSkills { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
因为您希望根据技能名称进行分析搜索,所以需要将其隔离为单独的索引条目.
public class PositionSearch
: AbstractIndexCreationTask<Employer, PositionSearchResultModel>
{
public PositionSearch()
{
Map = employers =>
from employer in employers
from position in employer.Positions
select new
{
EmployerId = employer.Id,
EmployerName = employer.Name,
PositionId = position.Id,
PositionTitle = position.Title,
position.Location,
position.Description,
position.RequiredSkills,
// Isolate the search property into it's own value
SkillsSearch = position.RequiredSkills.Select(x => x.Skill)
};
// you could store all fields if you wanted, but the search field
// doesn't need to be stored so that would be wasteful.
Store(x => x.PositionId, FieldStorage.Yes);
Store(x => x.PositionTitle, FieldStorage.Yes);
Store(x => x.Location, FieldStorage.Yes);
Store(x => x.Description, FieldStorage.Yes);
Store(x => x.RequiredSkills, FieldStorage.Yes);
// Any field you are going to use .Search() on should be analyzed.
Index(x => x.SkillsSearch, FieldIndexing.Analyzed);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我将投影指定为索引的结果.这是语法糖.将其关闭并没有错,但是你必须使用字符串指定搜索字段.
您还需要将搜索字段添加到结果类中
public string[] SkillsSearch { get; set; }
Run Code Online (Sandbox Code Playgroud)
它究竟是什么类型并不重要.字符串数组或集合就可以了.您也可以只使用字符串或对象,因为它只是相关的名称.
查询此索引时,请使用此.Search()方法,如下所示:
var results = session.Query<PositionSearchResultModel, PositionSearch>()
.Customize(x => x.WaitForNonStaleResults()) // only use this in testing
.Search(x=> x.SkillsSearch, "SkillName")
.ProjectFromIndexFieldsInto<PositionSearchResultModel>() // AsProjection would also work
.ToList();
Run Code Online (Sandbox Code Playgroud)
请注意,您必须存储这么多字段的唯一原因是因为您想要投影它们.如果将位置分隔为自己的文档,则会有更小的索引,而且项目的编制要少得多.请记住,在投影时,原始文档中的所有字段都已存在,并且直接来自文档存储,而不必复制到索引中.因此,如果您的原始文档更符合您期望的结果,那么可以做的工作就更少了.