使用RavenDB解决此问题时遇到困难。我有这些课程。 我从中排除了很多属性以保持示例简单。
public class Menu
{
public string Name { get; set; }
public List<NavigationNode> Nodes { get; set; }
}
public class NavigationNode
{
public string Text { get; set; }
public Guid? PageId { get; set; }
public string NodeType { get; set; }
public List<NavigationNode> Nodes { get; set; }
}
public class Page
{
public Guid PageId { get; set; }
public string Slug { get; set; }
}
因此,您可以看到这是关于渲染导航菜单。节点列表是分层的,可以在理论上无限深入(当然实际上只有2-4个子级别)。起初我将Slug存储在节点中但是意识到,如果页面Slug发生变化会发生什么,当页面更改slug时更改所有节点我将不得不遍历所有菜单,爬下层次结构并找到要更改的所有Slug值它们听起来不是最佳解决方案。
所以我认为应该可以构建一个索引,它将Page Slug与来自Node的其余数据结合在一个层次结构中。
我一直在阅读有关Map Reduce,Multimap和recurse的内容,但我甚至不知道从哪里开始。
我发现了http://ravendb.net/docs/2.0/client-api/querying/static-indexes/indexing-hierarchies
这是一个简单的例子,我试图让一些东西开始,我甚至无法让它工作,因为我真的不理解我链接到上面的页面上的例子。
public class NavigationIndex : AbstractIndexCreationTask<Menu>
{
public NavigationIndex()
{
Map = menus => from menu in menus
from node in Recurse(menu, x => x.Nodes)
select new
{
WhatIsThis = node // <- Why is this a collection?
};
}
}
根据示例节点,不应该是集合,而是实际的NavigationNode对象。
是否有可能在RavenDB中实现我想要的,以及我在示例中做错了什么?
请随意询问任何您感到困惑的事情。
我为这种困惑道歉。我会试着解释一下。
修改
将PageId更改为字符串不会有问题。我正在使用Guids,因为我需要能够在插入之前生成主键ID:s。无论如何,我想从索引查询的是一个导航链接的hiearachical树,其中包含Pages Slug。所以我可以递归地循环出网站上的导航菜单。
Matt Johnson的问题答案:
我只会按菜单名称
进行查询public class NavigationIndexItem { public string MenuName {get;组; } public string Text {get;组; } public string Slug {get;组; } public string NodeType {get;组; } public List ChildItems {get;组; } }
现在当我看到上面的课程时,我想我可能会走错路。
但无论如何,我会做一些小改动,谢谢Matt的回答。但是我仍然遇到和以前一样的问题。
示例中的这一行:其中node.PageId!= null
节点不是特定NavigationNode的实例,而是另一个集合,因此我无法检查其上的PageId属性。我只得到一个LINQ扩展列表。
答案 0 :(得分:3)
我正在对你想要的东西做一些假设。请参阅我对原始问题的评论。但我认为这就是你所追求的目标。
首先 - 您需要将Page
课程的ID更改为Id
而不是PageId
。这是Raven将使用您的guid作为其文档ID的一部分。真的,你最好使用字符串ID,但这仍然有用。
然后您可以执行以下操作:
public class NavigationIndex : AbstractIndexCreationTask<Menu>
{
public NavigationIndex()
{
Map = menus => from menu in menus
from node in Recurse(menu, x => x.Nodes)
where node.PageId != null
let page = LoadDocument<Page>("pages/" + node.PageId)
select new
{
menu.Name,
node.Text,
node.PageId,
page.Slug
};
}
}
这使用了RavenDB 2.0的新LoadDocument功能,它比你的场景更适合多地图。
答案 1 :(得分:0)
将其更改为:
from node in Recurse(menu, x => x.Nodes.AsEnumerable())