示例数据:
示例查询
CREATE (a1:A {title: "a1"})
CREATE (a2:A {title: "a2"})
CREATE (a3:A {title: "a3"})
CREATE (b1:B {title: "b1"})
CREATE (b2:B {title: "b2"})
MATCH (a:A {title: "a1"}), (b:B {title: "b1"})
CREATE (a)-[r:LINKS]->(b)
MATCH (a:A {title: "a2"}), (a1:A {title: "a1"})
CREATE (a)-[:CONNECTED]->(a1)
MATCH (a:A), (b:B) return a,b
目标:在where子句中找到一些连接
现在让我们写一些变体来找到A没有直接连接到B(a2和b3)
// Q1. Both work fine
MATCH (a:A) WHERE (a)--(:B) RETURN a
MATCH (a:A) WHERE (:B)--(a) RETURN a
// Q2. Works
MATCH (a:A)-[r]-(b:B) WHERE (a)-[r]-(b) RETURN a
// Q3. Fails
MATCH (a:A)-[r]-(b:B) WHERE (b)-[r]-(a) RETURN a
任何想法为什么Q2,Q3即使方向指定为双向也不会表现相同? 这是NEO4J的错误吗?
stdob的{strong> this answer 所有信用额度缩小 在我的另一个查询中发生的异常现象。
更新:将相同内容发布到NEO4J GitHub issues
更新:NEO4J已经接受了这个,因为它将在3.1
修复它答案 0 :(得分:1)
虽然这可能不是一个完整的答案,但评论的信息太多了。这应该有望提供一些有用的见解。
我认为这是一个错误。以下是应从样本数据中得到相同结果的一些变体。它们都应该传递给定的数据(传递返回任何东西)
MATCH (a:A)-[r]-(b:B) WHERE (b)-[r]-(a) RETURN *
- >失败
删除r
MATCH (a:A)--(b:B) WHERE (b)--(a) RETURN *
- >通过
MATCH (a:A)-[r]-(b:B) WHERE (b)--(a) RETURN *
- >通过
添加方向
MATCH (a:A)-[r]-(b:B) WHERE (b)<-[r]-(a) RETURN *
- &gt;通过
逆序
MATCH (a:A)-[r]-(b:B) WHERE (a)-[r]-(b) RETURN *
- &gt;通过
并且,从失败的测试的配置文件
+---------------------+----------------+------+---------+-----------+--------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+---------------------+----------------+------+---------+-----------+--------------+
| +ProduceResults | 1 | 0 | 0 | a | a |
| | +----------------+------+---------+-----------+--------------+
| +SemiApply | 1 | 0 | 0 | a, b, r | |
| |\ +----------------+------+---------+-----------+--------------+
| | +ProjectEndpoints | 1 | 0 | 0 | a, b, r | r, b, a |
| | | +----------------+------+---------+-----------+--------------+
| | +Argument | 2 | 1 | 0 | a, b, r | |
| | +----------------+------+---------+-----------+--------------+
| +Filter | 2 | 1 | 1 | a, b, r | a:A |
| | +----------------+------+---------+-----------+--------------+
| +Expand(All) | 2 | 1 | 3 | a, r -- b | (b)-[r:]-(a) |
| | +----------------+------+---------+-----------+--------------+
| +NodeByLabelScan | 2 | 2 | 3 | b | :B |
+---------------------+----------------+------+---------+-----------+--------------+
和等效的通过测试(逆序)
+---------------------+----------------+------+---------+-----------+--------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+---------------------+----------------+------+---------+-----------+--------------+
| +ProduceResults | 1 | 1 | 0 | a | a |
| | +----------------+------+---------+-----------+--------------+
| +SemiApply | 1 | 1 | 0 | a, b, r | |
| |\ +----------------+------+---------+-----------+--------------+
| | +ProjectEndpoints | 1 | 0 | 0 | a, b, r | r, a, b |
| | | +----------------+------+---------+-----------+--------------+
| | +Argument | 2 | 1 | 0 | a, b, r | |
| | +----------------+------+---------+-----------+--------------+
| +Filter | 2 | 1 | 1 | a, b, r | a:A |
| | +----------------+------+---------+-----------+--------------+
| +Expand(All) | 2 | 1 | 3 | a, r -- b | (b)-[r:]-(a) |
| | +----------------+------+---------+-----------+--------------+
| +NodeByLabelScan | 2 | 2 | 3 | b | :B |
+---------------------+----------------+------+---------+-----------+--------------+
注意每个步骤1之后的行数。同一计划不应产生不同的结果。我可以推测这是一个与图形修剪快捷方式相关的错误(即,一旦Neo4j在一个方向上遍历一条边,它就不会在相同的匹配中遍历同一条边。这是一个反周期的自动防故障/性能特征)因此,理论上,在从匹配部分的where部分反转顺序后,Neo4j必须遍历修剪边缘以验证关系。如果它是相同的方向,它会自动通过。如果Neo4j尝试反向执行相同的检查,则会因为该边缘已被修剪而失败。 (这只是理论而已。失败的验证在技术上反过来进行r验证)