简体   繁体   English

NEO4J Cypher查询:Where子句中的关系方向错误

[英]NEO4J Cypher Query: Relationship Direction Bug in Where Clause

Sample Data: 样本数据:

在此输入图像描述

Sample Query 示例查询

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

Objective: Finding some connections in the where clause 目标:在where子句中查找一些连接

Now lets write some variations to find A's not directly connected to B (a2 and b3) 现在让我们写一些变化来找到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

Any idea why Q2, Q3 are not behaving the same way even if the direction is specified as bi-directional? 知道为什么即使方向被指定为双向,Q2,Q3的行为也不一样吗? Is this a NEO4J bug? 这是NEO4J的错误吗?

All credits to stdob at this answer for narrowing down the anomaly that was happening in my other query. 所有学分stdob这个答案对于缩小这是我在其他的查询发生异常。


Update: Posted the same to the NEO4J GitHub issues 更新:发布相同的NEO4J GitHub问题

Update: NEO4J has accepted this as a bug are will be fixing it at 3.1 更新:NEO4J已接受此错误,将修复它在3.1

在此输入图像描述

While this might not be a complete answer, it is too much info for a comment. 虽然这可能不是一个完整的答案,但评论的信息太多了。 This should hopefully provide some helpful insight though. 这应该有希望提供一些有用的见解。

I would consider this a bug. 我认为这是一个错误。 Below are some variations of what should give the same results from the sample data. 以下是应从样本数据中得到相同结果的一些变体。 They should all pass with the given data (pass being return anything) 它们都应该传递给定的数据(传递返回任何东西)

MATCH (a:A)-[r]-(b:B) WHERE (b)-[r]-(a) RETURN * -> fails MATCH (a:A)-[r]-(b:B) WHERE (b)-[r]-(a) RETURN * - >失败

remove r 删除r
MATCH (a:A)--(b:B) WHERE (b)--(a) RETURN * -> pass MATCH (a:A)--(b:B) WHERE (b)--(a) RETURN * - >通过
MATCH (a:A)-[r]-(b:B) WHERE (b)--(a) RETURN * -> pass MATCH (a:A)-[r]-(b:B) WHERE (b)--(a) RETURN * - >通过

add direction 添加方向
MATCH (a:A)-[r]-(b:B) WHERE (b)<-[r]-(a) RETURN * -> pass MATCH (a:A)-[r]-(b:B) WHERE (b)<-[r]-(a) RETURN * - >通过

reverse order 相反的顺序
MATCH (a:A)-[r]-(b:B) WHERE (a)-[r]-(b) RETURN * -> pass MATCH (a:A)-[r]-(b:B) WHERE (a)-[r]-(b) RETURN * - >传球

And, from the profile of the failed test 并且,从失败的测试的配置文件

+---------------------+----------------+------+---------+-----------+--------------+
| 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           |
+---------------------+----------------+------+---------+-----------+--------------+

and the equivalent passed test (reverse order) 和等效的通过测试(逆序)

+---------------------+----------------+------+---------+-----------+--------------+
| 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           |
+---------------------+----------------+------+---------+-----------+--------------+

Notice the row count after step 1 in each. 请注意每个步骤1之后的行计数。 The same plan should not produce different results. 同一计划不应产生不同的结果。 I can speculate that is is a bug related to the graph pruning shortcuts (namely, once Neo4j traverses an edge in one direction, it will not traverse back on the same edge in the same match. This is an anti-cycle fail-safe/performance feature) So, in theory, after reversing the order in the where part from the match part, Neo4j has to traverse a pruned edge to validate the relationship. 我可以推测这是一个与图形修剪快捷方式相关的错误(即,一旦Neo4j在一个方向上遍历一条边,它就不会在相同的匹配中遍历同一条边。这是一个反周期的自动防故障/性能特征)因此,理论上,在从匹配部分的where部分反转顺序后,Neo4j必须遍历修剪边缘以验证关系。 If it is the same direction, it auto-passes. 如果它是相同的方向,它会自动通过。 If Neo4j tries to do the same check in reverse, it fails because that edge has been pruned. 如果Neo4j尝试反向执行相同的检查,则会因为该边缘已被修剪而失败。 (This is just theory though. The validation that is failing is technically on the r validation in reverse) (这只是理论上的。失败的验证在技术上反过来验证)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM