从RavenDB中的祖先文档继承数据

从RavenDB中的祖先文档继承数据,ravendb,Ravendb,我使用RavenDB存储三种类型的课程:单元、课程和活动。这三种类型都继承自CoursulumBase: public abstract class CurriculumBase { public string Id { get; set; } public string Title { get; set; } public List<string> SubjectAreaIds { get; set; } // non-relevant proper

我使用RavenDB存储三种类型的课程:单元、课程和活动。这三种类型都继承自CoursulumBase:

public abstract class CurriculumBase
{
    public string Id { get; set; }
    public string Title { get; set; }
    public List<string> SubjectAreaIds { get; set; }
    // non-relevant properties removed
}
公共抽象类课程库
{
公共字符串Id{get;set;}
公共字符串标题{get;set;}
公共列表SubjectAreaId{get;set;}
//删除不相关的属性
}
这些文档具有层次关系,因此我将层次结构建模为一个单独的文档,如下所示:

公共类课程层次结构
{
公共类节点
{
公共字符串ID{get;set;}
公共字符串标题{get;set;}
公共列表子项{get;set;}
公共节点()
{
Children=新列表();
}
}
公共列表{get;set;}
公共课程层次结构()
{
根课程=新列表();
}
}
我需要能够搜索所有课程文档。对于简单的属性,使用多映射索引似乎很容易做到这一点

但是,我需要能够搜索的属性之一(与其他搜索条件结合使用)是SubjectAreaId。我需要能够得到课程,它或其任何祖先有指定的学科领域id(s)。换句话说,出于搜索目的,文档应该继承其祖先的SubjectAreaID


我已经考虑过取消SubjectAreaID的规范化,并在每个文档中存储完整的SubjectAreaID计算集,但这需要在层次结构本身或给定文档的任何祖先的SubjectAreaID发生更改时进行更新。我希望这是我可以通过索引实现的,或者可能需要一种完全不同的方法

您可以在索引期间使用LoadDocument加载父级


我遇到的主要挑战是,我在课程层次结构中编写了获取文档祖先的代码,但在索引过程中,此代码不可执行

为了解决这个问题,我在CoursulumHierarchy中添加了一个只读属性,该属性为每个文档生成一个祖先词典:

public Dictionary<string, IEnumerable<string>> AncestorLookup
{
    get
    {
        // Not shown: build a dictionary where the key is an  
        // ID and the value is a list of the IDs for 
        // that item's ancestors
    }
}
公共字典查找
{
得到
{
//未显示:在键为
//ID,该值是的ID列表
//那东西的祖先
}
}
此词典由Raven序列化,因此可用于索引

然后我的索引结果如下所示:

public class Curriculum_Search : AbstractMultiMapIndexCreationTask
{
    public Curriculum_Search()
    {
        AddMap<Activity>(
            activities =>
                from activity in activities
                let hierarchy = 
                    LoadDocument<CurriculumHierarchy>("curriculum_hierarchy")
                let ancestors = 
                    LoadDocument<CurriculumBase>(hierarchy.AncestorLookup[activity.Id])
                select new
                {
                    subjectAreaIds = ancestors.SelectMany(x => x.SubjectAreaIds).Distinct().Union(activity.SubjectAreaIds),
                });

       // Not shown: Similar AddMap statements for Lessons and Units
    }
}
公共类课程\u搜索:AbstractMultiMapIndexCreationTask
{
公共课程搜索()
{
地址图(
活动=>
活动中的活动
让层次结构=
LoadDocument(“课程层次结构”)
让祖先=
LoadDocument(hierarchy.AncestorLookup[activity.Id])
选择新的
{
subjectAreaIds=祖先。选择多个(x=>x.subjectAreaIds).Distinct().Union(activity.subjectAreaIds),
});
//未显示:课程和单元的类似AddMap语句
}
}

我有点担心表现,但由于课程文档总数不到2000份,所以这似乎表现得可以接受

我对LoadDocument很熟悉,但我的挑战是使项目的祖先可用于Raven索引。我在解决方案中添加了一个答案。
public class Curriculum_Search : AbstractMultiMapIndexCreationTask
{
    public Curriculum_Search()
    {
        AddMap<Activity>(
            activities =>
                from activity in activities
                let hierarchy = 
                    LoadDocument<CurriculumHierarchy>("curriculum_hierarchy")
                let ancestors = 
                    LoadDocument<CurriculumBase>(hierarchy.AncestorLookup[activity.Id])
                select new
                {
                    subjectAreaIds = ancestors.SelectMany(x => x.SubjectAreaIds).Distinct().Union(activity.SubjectAreaIds),
                });

       // Not shown: Similar AddMap statements for Lessons and Units
    }
}