在.net中表示多级分组的体系结构

在.net中表示多级分组的体系结构,.net,architecture,grouping,.net,Architecture,Grouping,我有一个来自Lucene.net的键值文档列表,我希望能够根据不同的值和用户输入对它们进行分组。所以基本上我有下面的列表 Doc#1 - Weight:10;Size:20;ExpiresIn:90days Doc#2 - Weight:10;Size:30;ExpiresIn:90days Doc#3 - Weight:10;Size:20;ExpiresIn:30days Doc#4 - Weight:10;Size:20;ExpiresIn:30days 我想让用户告诉我:按尺寸分组,然

我有一个来自Lucene.net的键值文档列表,我希望能够根据不同的值和用户输入对它们进行分组。所以基本上我有下面的列表

Doc#1 - Weight:10;Size:20;ExpiresIn:90days
Doc#2 - Weight:10;Size:30;ExpiresIn:90days
Doc#3 - Weight:10;Size:20;ExpiresIn:30days
Doc#4 - Weight:10;Size:20;ExpiresIn:30days
我想让用户告诉我:按尺寸分组,然后按重量分组,结果如下

Size: 20
 Weight: 10
  Count: 3
  Doc#1, Doc#3, Doc#4
Size: 30
 Weight: 10
  Count: 1
  Doc#2
但他也可以告诉我去参加ExpiresIn小组:

ExpiresIn: 90Days
 Count: 2
 Doc#1, Doc#2
ExpiresIn: 30Days
 Count: 2
 Doc#3, Doc#4
我的问题其实不是速度(尽管在巨大数据集的情况下肯定会出现),而是架构。我想知道如何代表我拥有的各种实体:

  • 一个叶型节点,包含文档列表(以及它们的计数,平凡)(第一个示例中的叶节点)
  • 位于叶节点正上方,包含叶列表(第一个示例中的权重)
  • 一个从上到下的节点,包含一个节点列表(第一个示例中的大小)
我试着从一个包含泛型节点列表的公共抽象节点开始:然而,当我尝试从顶部注入文档时,这种方法就会崩溃,因为每个节点都不知道自己的上下文,也不知道应该在他之后创建什么

Public MustInherit Class Node(Of T)
    Implements IEnumerable(Of T)

    Private InnerValue As String
    Private InnerGrouping As String
    Protected InnerData As New List(Of T)

    MustOverride Sub AddGroupingElement(element As LuceneSearchResultsInfo)
End Class

Public Class LeafNode
    Inherits Node(Of LuceneSearchResultsInfo)

    Public Overrides Sub AddGroupingElement(element As LuceneSearchResultsInfo)
        InnerData.Add(element)
    End Sub
End Class

Public Class CommonNode
    Inherits Node(Of CommonNode)

    Public Overrides Sub AddGroupingElement(element As LuceneSearchResultsInfo)
        Dim InterestedNode = InnerData.FirstOrDefault(Function(n) n.Value = element.Field(Grouping))
        If (InterestedNode Is Nothing) Then
            InterestedNode = New CommonNode ' argh, i'm stuck, i don't know the rest of the context
        End If

    End Sub
End Class

我正在考虑存储一个简单的词汇表,其中文档的完整路径存储为键。它更简单,但并不像专用结构那样令人愉快。因此,欢迎任何想法:)

节点不能在这种结构中的任意级别插入。(您的树是按属性分组的文档列表的表示形式。在任意级别插入意味着属性一致性丢失,就像您向表中添加单个单元格,而不是一行表示具有完整属性集的文档一样。)因此,项的插入和删除应由树本身维护

考虑这样的类结构(C#,因为我不擅长VB语法):

classtableastree
{
分组节点根;
公共空白插入(LuceneSearchResultsInfo sr)
{
/*递归插入*/
InsertToGroup(根,sr);/*-根节点将存储所有项*/
}
public void InsertToGroup(GroupingNode节点,LuceneSearchResultsInfo sr)
{
节点.Documents.Add(sr.Document);
//示例:查找关键字为当前单据权重的“权重”组。
var childGroup=ChildGroups.First(g=>g.GroupKey==sr.Fields(g.GroupFieldName));/*如果没有值的组,则创建*/
插入组(儿童组,sr);
}
}
类分组节点
{   
字符串GroupKey;/*组键值=1或2或3英寸(大小=1,2,3),对根没有意义*/
字符串GroupFieldName;/*组字段名(大小),根为空*/
列出文档;/*该级别的文档-您可以为每个级别或上一个级别之前的级别添加它们*/
列出儿童组;
}

使用它,您将能够获取每个分组级别的文档列表。

节点不能在这种结构中的任意级别插入。(您的树是按属性分组的文档列表的表示形式。在任意级别插入意味着属性一致性丢失,就像您向表中添加单个单元格,而不是一行表示具有完整属性集的文档一样。)因此,项的插入和删除应由树本身维护

考虑这样的类结构(C#,因为我不擅长VB语法):

classtableastree
{
分组节点根;
公共空白插入(LuceneSearchResultsInfo sr)
{
/*递归插入*/
InsertToGroup(根,sr);/*-根节点将存储所有项*/
}
public void InsertToGroup(GroupingNode节点,LuceneSearchResultsInfo sr)
{
节点.Documents.Add(sr.Document);
//示例:查找关键字为当前单据权重的“权重”组。
var childGroup=ChildGroups.First(g=>g.GroupKey==sr.Fields(g.GroupFieldName));/*如果没有值的组,则创建*/
插入组(儿童组,sr);
}
}
类分组节点
{   
字符串GroupKey;/*组键值=1或2或3英寸(大小=1,2,3),对根没有意义*/
字符串GroupFieldName;/*组字段名(大小),根为空*/
列出文档;/*该级别的文档-您可以为每个级别或上一个级别之前的级别添加它们*/
列出儿童组;
}

使用它,您将能够获得每个分组级别的文档列表。

让问题成熟一点后,我发现我所要求的不是我可以用树表示的东西;然而,如果我们想在所有级别上获得相同的功能,mikalai提供了一个很好的解决方案;但是,如果我们想在所有级别上获得相同的功能,mikalai提供了一个很好的解决方案。
class TableAsTree
{
    GroupingNode Root;  

    public void Insert(LuceneSearchResultsInfo sr)
    {
        /* Recursively insert */
        InsertToGroup(Root, sr); /* - root node would store all items */

    }

    public void InsertToGroup(GroupingNode node, LuceneSearchResultsInfo sr)
    {
        node.Documents.Add(sr.Document);
        //sample: Find "Weight" group with key = weight of current doc.
        var childGroup = ChildGroups.First(g => g.GroupKey == sr.Fields(g.GroupFieldName)); /*create if there is no group for the value*/
        InsertToGroup(childGroup, sr);
    }
}

class GroupingNode<TDocument>
{   
    string GroupKey;                    /* Group key value = 1 or 2 or 3 in (Size=1,2,3), no meaning for root */
    string GroupFieldName;              /* Group field name (Size), null for root */
    List<TDocument> Documents;          /* Documents at the level - you can add them for each level, or of the level before the last one */ 
    List<GroupingNode> ChildGroups;
}