我正在接受我的一个老项目,其效率和效率是关键。我解析了100 GB的XML数据。对于每个XML树(数百万个),使用一些XML属性从中扣除模式。但是,对于这个问题,我将大大简化一些事情 - 但重要的是要记住,有很多数据,并且快速处理和整齐地将结果存储在XML中非常重要。此外,还需要遍历生成的XML树。事实上,它将作为BaseX中使用的自定义索引机制,但我稍后会再回过头来看。
从每个树(及其子树,但现在不重要)创建一个基于根节点的直接子节点的模式。作为基本示例,请使用以下XML树:
<node letter="X">
<node letter="A"/>
<node letter="B"/>
<node letter="C"/>
<node letter="D"/>
</node>
通过获取所有孩子的字母属性并对其进行排序并加入它们来创建模式。在这种情况下,模式将是ABCD
。
对于每棵树,也生成所有可能的子树(顺序不重要,最小组合2),即,子项的所有可能组合,并且生成它们的模式。我不包括组合树的XML,但除了ABCD
之外,可能的模式是:
AB
ABC
ABD
AC
ACD
AD
BC
BCD
BD
CD
在层次结构中,它们看起来像这样(注意终端节点中的重复)。
此外,应该在生成的XML中以某种方式指示我们开始的完整模式,以指示它是树中的“主要”模式。最终,我希望恢复从给定模式派生的所有模式(参见后面的内容)并将其过滤为仅仅是'主要'模式的模式。
从查询的角度来看,您可以argue that I am doing a bottom-up look-up. If I am looking for a generalized pattern, e.g. AB, the more specific patterns should also be found because
AB is part of
ABCD。因此,如果我要使用上面的数据查找模式AB
,我想找到
ABCD
ABC
ABD
可能很清楚,这里有两个步骤。首先,概括一级:AB -> ABC,ABD
然后ABC->ABCD
(再次ABD->ABDC
,但每个结果只能找到一次)。中间步骤ABC
和ABD
对我来说也很重要,不仅仅是最终的ABCD
结果。
我所面临的问题是如何有效地存储树,例如图像中显示的树,以便它以我所讨论的方式查询; 2.尽可能稀疏而不丢失任何节点; 3.高效建设。后一点对于这个问题不太重要,因为我将自己实现构建脚本 - 这将在Python 3.6中完成。
我到目前为止的想法是拥有一个相当扁平的结构,通过'coindexing'直接父节点来工作。它看起来像这样:
<tree>
<node pattern="AB" index="1">
<parentnode coindex="7"/> <!-- ABC -->
<parentnode coindex="8"/> <!-- ABD -->
</node>
<node pattern="AC" index="2">
<parentnode coindex="7"/> <!-- ABC -->
<parentnode coindex="9"/> <!-- ACD-->
</node>
<node pattern="AD" index="3">
<parentnode coindex="8"/> <!-- ABD -->
<parentnode coindex="9"/> <!-- ACD -->
</node>
<node pattern="BC" index="4">
<parentnode coindex="7"/> <!-- ABC -->
<parentnode coindex="10"/> <!-- BCD -->
</node>
<node pattern="BD" index="5">
<parentnode coindex="8"/> <!-- ABD -->
<parentnode coindex="10"/> <!-- BCD -->
</node>
<node pattern="CD" index="6">
<parentnode coindex="9"/> <!-- ACD -->
<parentnode coindex="10"/> <!-- BCD -->
</node>
<node pattern="ABC" index="7">
<parentnode coindex="11"/> <!-- ABCD -->
</node>
<node pattern="ABD" index="8">
<parentnode coindex="11"/> <!-- ABCD -->
</node>
<node pattern="ACD" index="9">
<parentnode coindex="11"/> <!-- ABCD -->
</node>
<node pattern="BCD" index="10">
<parentnode coindex="11"/> <!-- ABCD -->
</node>
<node pattern="ABCD" index="11" isMain="true"/>
</tree>
通过这样做,我想可以得到所有链接在一起的模式。例如,如果我现在寻找AB,我希望得到那些节点的子节点(parentnode
)并获取这些索引并使用它们来寻找直接父节点。然后应该重复该过程,直到没有元素留下一个coindex(例如在这种情况下为ABCD
)。
想象一下,有数千个这样的XML元素,主要的元素用isMain
表示。请注意,isMain
不一定是没有父节点子节点的模式!结果是所有原始XML树的累积。这意味着在某些情况下,模式可能是主要模式,而在其他情况下,模式可能是组合的一部分。在这种情况下,node
用isMain
表示,因为在原始XML中,有一些树将此模式作为其主要模式。
到目前为止,这只是我的想法,但我不确定是否有更好的方法,或者更重要的是,如果可以在BaseX中轻松查询。基本上使用给定的输入AB
我想通过使用索引检索所有相关的pattern
s(ABC,ABD,ABCD),然后通过仅检索{{1}中的一个来过滤这些结果}}。我期待看到更好的想法,以及在BaseX中查询它们的方法。如果我的想法很好,那么我希望看到一个在单个xquery表达式中捕获查询的好方法。
答案 0 :(得分:1)
我没有完全通过将层次结构数据放到平面结构中而仍然使用高效的XML处理器BaseX来实现您想要的目标。
我认为将数据放入它已经表示的逻辑结构中,并使用索引来高效地查询数据是更自然(更快捷)的方法。
因此,您只需按原样使用分层结构,例如:
<tree>
<node pattern="ABCD">
<node pattern="ABC">
<node pattern="AB"/>
<node pattern="AC"/>
<node pattern="BC"/>
</node>
<node pattern="ABD">
<node pattern="AB"/>
<node pattern="AD"/>
<node pattern="BD"/>
</node>
</node>
</tree>
因此,我想您出于性能原因选择了该格式。但是在建立数据库时,您应该创建一个属性索引,即所有属性值都将被索引。通常,对于更常见的查询,应将其重写,但是您可以直接使用属性索引。例如,我有一个50GB以上的数据库,其中包含英语维基百科的转储。例如,我选择搜索页面List of Dragon Ball characters
:
db:attribute("wikipedia", "List of Dragon Ball characters")/parent::*
这大约需要20毫秒才能在我的计算机上执行。
类似地,您可以简单地搜索模式并沿着树上走:
db:attribute("<YOUR_DB>", "AB")/ancestor::node/@pattern => distinct-values()
考虑到您首先利用索引,然后简单地向上移动父母,这应该尽可能快。