OrientDB SQL为使用OR过滤器的复杂查询和简单查询的级联提供了不同的结果

时间:2017-08-17 11:26:20

标签: orientdb

我开始使用OrientDB并在复杂查询中遇到一些奇怪的行为。

我想获得几个节点的图形邻域。我对string属性中包含“AD”子字符串的节点,包含值ontology_id的属性D017628的节点以及与深度最多为3的节点相关的节点感兴趣。

有人可以解释为什么我对“OR”的复杂查询有不同的结果: TRAVERSE * FROM (SELECT * FROM V WHERE ontology_id="D017628" or string LIKE "%AD%") WHILE $depth<=3

如果我将上面的查询分解为2个单独的查询并单独运行,我可以获得更多结果: TRAVERSE * FROM (SELECT * FROM V WHERE ontology_id="D017628") WHILE $depth<=3 TRAVERSE * FROM (SELECT * FROM V WHERE string LIKE "%AD%") WHILE $depth<=3

为什么会这样?在SELECT中使用OR语句加入不同的标准是不正确的?

1 个答案:

答案 0 :(得分:0)

要理解TRAVERSE语句,您必须考虑两个细节:

  • 默认情况下,遍历是深度优先的
  • 遍历的节点永远不会被重新遍历。

现在考虑一个由四个顶点组成的图表:

A, B, C, D

连接如下:

A -> B -> C -> D
A -> C 

(由A,B,C组成的三角形,加上从C到D的边缘)

现在,假设您从A开始执行TRAVERSE,$ depth&lt; = 2

您可以进行此遍历

A (depth = 0)
A -> B (depth = 1)
B -> C (depth = 2)
C -> D (depth = 3, so D is discarded)
A -> C (you encounter C, that was already traversed, so this path is discarded)

此遍历的结果当然是A, B, C

现在考虑(纯粹的运气)遍历从另一条路径开始:

A (depth = 0)
A -> C (depth = 1)
C -> D (depth = 2)
A -> B (depth = 1)
B -> C (you encounter C, that was already traversed, so this path is discarded)

这种情况下的结果是A, C, D, B

如您所见,根据图表的遍历方式,您有两种不同的结果。

这里可能的解决方案是尝试强制遍历使用广度优先策略:

TRAVERSE * FROM (SELECT * FROM V WHERE ontology_id="D017628" or string LIKE "%AD%") WHILE $depth<=3 STRATEGY BREADTH_FIRST

这会有所帮助,但可能无法彻底解决问题。

另一种可能的解决方案是使用unionAll()编写单个查询:

SELECT unionAll($a, $b)
LET
$a = (TRAVERSE * FROM (SELECT * FROM V WHERE ontology_id="D017628") WHILE $depth<=3),
$b = (TRAVERSE * FROM (SELECT * FROM V WHERE string LIKE "%AD%") WHILE $depth<=3)

如果您正在进行实际的图遍历(因此可以用TRAVERSE *替换TRAVERSE both()),则可以使用MATCH语句重写查询(MATCH不会丢弃重复项):

MATCH
   {class:V, as:a, where:(ontology_id="D017628" or string LIKE "%AD%")} -E- {as:b, while:($depth < 3)}
RETURN $elements