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

时间:2015-06-09 20:49:25

标签: ravendb

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

public abstract class CurriculumBase
{
    public string Id { get; set; }
    public string Title { get; set; }
    public List<string> SubjectAreaIds { get; set; }
    // non-relevant properties removed
}

这些文档具有层次关系,因此我已按照此处的建议将层次结构建模为单独的单个文档:Modelling Hierarchical Data with RavenDB

public class CurriculumHierarchy
{
    public class Node
    {
        public string CurriculumId { get; set; }
        public string Title { get; set; }
        public List<Node> Children { get; set; }

        public Node()
        {
            Children = new List<Node>();
        }
    }

    public List<Node> RootCurriculum { get; set; }

    public CurriculumHierarchy()
    {
        RootCurriculum = new List<Node>();
    }
}

我需要能够在所有课程文档中进行搜索。对于简单属性,这似乎很容易与多映射索引。

然而,我需要能够搜索的其中一个属性(与其他搜索条件结合使用)是SubjectAreaId。我需要能够获得或其任何祖先具有指定主题区域ID的课程。换句话说,出于搜索目的,文档应该继承其祖先的subjectAreaIds。

我考虑过去标准化subjectAreaIds,并在每个文档中存储完整计算的subjectAreaIds集,但只要层次结构本身或任何给定文档的祖先的subjectAreaIds发生更改,就需要更新。我希望这是我可以用索引完成的事情,或者可能需要完全不同的方法。

2 个答案:

答案 0 :(得分:2)

您可以使用LoadDocument在索引编制期间加载父项。

http://ravendb.net/docs/article-page/3.0/csharp/indexes/indexing-related-documents

答案 1 :(得分:0)

我遇到的主要挑战是我在CurriculumHierarchy中编写了代码以获取文档的祖先,但此代码在索引编制期间不可执行。

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

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

此词典由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
    }
}

我对性能有点担心,但由于总课程文件不足2000本,这似乎表现得令人满意。