我在使用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存储在Node中,但意识到,如果页面Slug更改,更改所有节点时,我必须遍历所有菜单,沿着层次结构向下爬并找到所有那些Slug值来更改它们,这听起来不像是最佳解决方案。
所以我想应该可以构建一个索引,将页面Slug与Node中的其余数据结合在分层结构中。
我一直在阅读Map Reduce、Multimap和递归的相关内容,但我甚至不知道从哪里开始。
我发现了这个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。无论如何,我想从索引中查询包含页面Slug的导航链接的分层树形结构。这样我就可以在网站上递归循环出导航菜单。
回答Matt Johnson的问题:
1.我想要一个类的输出,您可以在下面看到
2.Page是一个单独的文档
3.我只会按Menu Name查询 public class NavigationIndexItem{ public string MenuName { get; set; } public string Text { get; set; } public string Slug { get; set; } public string NodeType { get; set; } public List ChildItems { get; set; } }
现在当我看到上面的类时,我觉得我可能走错了一点。
但无论如何,我会进行一些小的更改,并感谢马特的回答。然而,我仍然遇到了之前的同样问题。
你示例中的这一行:where node.PageId != null
node不是特定NavigationNode的实例,而是另一个集合,所以我无法检查它的PageId属性。我只能获得LINQ扩展列表。
Page
是一个单独的文档吗?如果是,您是否坚持使用Guid标识符?虽然可以实现,但Raven更适用于字符串标识符。3)您想通过什么查询? - Matt Johnson-Pint