6

我在使用 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 与来自节点的其余数据以分层结构相结合。

我一直在阅读有关 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:s。无论如何,我想从索引中查询的是包含 Pages Slug 的导航链接的层次结构树。所以我可以递归地循环出网站上的导航菜单。

回答马特约翰逊的问题:

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

    公共类 NavigationIndexItem{ 公共字符串 MenuName { 获取;放; } 公共字符串文本 { 获取;放; } 公共字符串蛞蝓 { 得到;放; } 公共字符串节点类型 { 获取;放; } 公共列表 ChildItems { 获取;放; } }

现在,当我看到上面的课程时,我想我可能有点走错路了。

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

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

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

4

2 回答 2

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功能,它比多地图更适合您的场景。

于 2013-02-01T17:04:04.383 回答
0

将其更改为:

                            from node in Recurse(menu, x => x.Nodes.AsEnumerable())
于 2013-01-31T01:39:59.123 回答