我在orientdb中构建了一个树,该树在自下而上的方向上具有大量节点和边缘。我想收到那棵树的所有叶子(每片叶子都有@class LEAF
),它们符合某个范围条件(例如val> 150和val <300):
示例:
o
/ \
o o
/ / \
o o o
210 120 /\
270 180
结果:210、180、270
到目前为止,我尝试使用以下查询:
SELECT FROM(TRAVERSE IN() FROM #123:123) WHERE value > 150 and value < 300
这在一些元素上运行良好,但是性能随着叶子数量的增加而下降。所以我的问题是:
答案 0 :(得分:0)
要提高性能,请尝试考虑查询应该执行的最少工作量,以找到正确的叶子:您要查找具有某些值的叶子>是某些树的一部分。
因此,您只想选择两个条件都成立的叶子。但是,除非您以某种方式为叶子提供信息,否则叶子不知道它们属于哪棵树。幸运的是,OrientDB允许您向边缘(或叶子本身)添加属性,从而使这一工作变得非常容易。
因此,在这种情况下,建议您将树的名称添加到该树的每个边缘。这样,每个叶子都会“通过关联”“知道”它属于哪棵树。
例如,让我们创建示例树:
CREATE CLASS Node EXTENDS V
CREATE PROPERTY Node.name INTEGER
CREATE VERTEX Node SET name = 1
CREATE VERTEX Node SET name = 2
CREATE VERTEX Node SET name = 3
CREATE VERTEX Node SET name = 4
CREATE CLASS LEAF EXTENDS V
CREATE PROPERTY LEAF.val FLOAT
CREATE VERTEX LEAF SET val = 210
CREATE VERTEX LEAF SET val = 120
CREATE VERTEX LEAF SET val = 270
CREATE VERTEX LEAF SET val = 180
CREATE CLASS C EXTENDS E
CREATE PROPERTY C.tree STRING
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 1) TO (SELECT * FROM Node WHERE name = 2) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 1) TO (SELECT * FROM Node WHERE name = 3) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 3) TO (SELECT * FROM Node WHERE name = 4) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 2) TO (SELECT * FROM LEAF WHERE val = 210) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 3) TO (SELECT * FROM LEAF WHERE val = 120) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 4) TO (SELECT * FROM LEAF WHERE val = 270) SET tree = 'example'
CREATE EDGE C FROM (SELECT * FROM Node WHERE name = 4) TO (SELECT * FROM LEAF WHERE val = 180) SET tree = 'example'
请注意EDGE
类C
如何包含属性C.tree
(字符串)。在Nodes
和LEAFs
之间创建边缘时,请为每个EDGE
指定树的名称。在这种情况下,我向每个边缘添加了SET tree = 'example'
。
结果如下:
接下来,在LEAF.val
上创建索引(以加快值搜索),并在C.tree
上创建索引以快速识别每个叶子所属的树:
CREATE INDEX leafIndex ON LEAF (val) NOTUNIQUE
CREATE INDEX connectIndex ON C (tree) NOTUNIQUE
您现在可以在叶子上执行性能卓越的查询,如下所示:
SELECT * FROM LEAF WHERE inE('C').tree = ["example"] AND val > 150 and val < 300
此查询执行以下操作:
in
的{{1}}边,并且C
属性等于“ example” tree
属性此方法还避免了使用val
,这比仅使用traverse
更为昂贵。
结果正是您想要的:
从查询说明中我们还可以看到优化引擎正在使用索引:
select
即使您有很多叶子,此查询也应该表现良好。
祝你好运!
PS。您还可以将树的名称添加到每个顶点(而不是边),这也是一种解决方案!但是在那种情况下,请记住当一片叶子是多棵树的一部分时会发生什么。