【问题标题】:Inheriting data from ancestor documents in RavenDB从 RavenDB 中的祖先文档继承数据
【发布时间】:2015-06-16 06:30:02
【问题描述】:

我正在使用 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 发生变化时,都需要进行更新。我希望这是我可以通过索引完成的事情,或者可能需要一种完全不同的方法。

【问题讨论】:

    标签: ravendb


    【解决方案1】:

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

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

    【讨论】:

    • 我熟悉 LoadDocument,但我面临的挑战是让项目的祖先可用于 Raven 索引。我在我的解决方案中添加了答案。
    【解决方案2】:

    我遇到的主要挑战是我在 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 个,这似乎可以接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      • 2016-01-04
      • 2015-01-02
      • 1970-01-01
      相关资源
      最近更新 更多