RavenDB和分层文档

时间:2013-01-30 14:37:18

标签: recursion ravendb hierarchical-data

使用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的问题答案:

  1. 我想要一个类的输出,你可以在下面看到
  2. Page是一个单独的文档
  3. 我只会按菜单名称

    进行查询

    public class NavigationIndexItem {     public string MenuName {get;组; }     public string Text {get;组; }     public string Slug {get;组; }     public string NodeType {get;组; }     public List ChildItems {get;组; }     }

  4. 现在当我看到上面的课程时,我想我可能会走错路。

    但无论如何,我会做一些小改动,谢谢Matt的回答。但是我仍然遇到和以前一样的问题。

    示例中的这一行:其中node.PageId!= null

    节点不是特定NavigationNode的实例,而是另一个集合,因此我无法检查其上的PageId属性。我只得到一个LINQ扩展列表。

2 个答案:

答案 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())