【问题标题】:RavenDb static Index: query on child collection objectsRavenDb 静态索引:对子集合对象的查询
【发布时间】:2013-01-27 21:56:25
【问题描述】:

我的文档结构如下:

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

但是,当我尝试执行以下查询时:

var results = session.Query<PositionSearchResultModel, PositionSearch>()
    .Customize(x => x.WaitForNonStaleResults())
    .Where(x=>x.RequiredSkills.Any(y=>y.Skill == "SkillName"))
    .ProjectFromIndexFieldsInto<PositionSearchResultModel>()
    .ToList();

我收到以下错误:

System.ArgumentException:
    The field 'RequiredSkills_Skill' is not indexed,
    cannot query on fields that are not indexed

谁能看到我做错了什么或为我建议另一种方法?

谢谢,

詹姆斯

更新我的视图模型 - 谢谢:

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

【问题讨论】:

  • 您将索引条目与索引结果混淆了。请提供您的PositionSearchResultModel 课程,我将提供完整的解决方案。谢谢。
  • 我看到您试图将该字段标记为已分析。您想要技能名称完全匹配吗?还是您想要进行分析搜索?
  • 我认为这需要进行分析搜索,因为我可能并不总是拥有完整的技能名称。

标签: indexing ravendb


【解决方案1】:

由于您要针对技能名称进行分析搜索,因此需要将其隔离为单独的索引条目。

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

请注意,我将投影指定为索引的结果。这是语法糖。关闭它并没有错,但是您必须使用字符串指定您的搜索字段。

您还需要将搜索字段添加到结果类中

public string[] SkillsSearch { get; set; }

它是什么类型真的没关系。字符串数组或集合就可以了。您也可以只使用字符串或对象,因为它只是相关的名称。

查询此索引时,使用.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();

请注意,您必须存储这么多字段的唯一原因是您想要投影它们。如果您将这些职位分成他们自己的文档,您将拥有更小的索引和更少的项目。请记住,当您进行投影时,原始文档中的所有字段都已经存在并且直接来自文档存储,而不必复制到索引中。因此,如果您的原始文档更接近您想要的结果,那么要做的工作就会更少。

【讨论】:

  • 我需要做类似的事情,但我不需要查看结果,只需检查技能是否存在。这是否意味着我不需要存储这些字段?
  • @DanyW - 如果您只是使用 where 子句中的字段,则不需要存储它们。仅当您要将它们投影回结果集时才需要存储它们。
猜你喜欢
  • 2016-05-21
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多