我使用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发生更改,就需要更新。我希望这是我可以用索引完成的事情,或者可能需要完全不同的方法。
答案 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本,这似乎表现得令人满意。