我开始使用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语句加入不同的标准是不正确的?
答案 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