Neo4j Version: 4.2.4
Operating System: MacOs
API: Cypher
According to the documentation, the same path cannot contain the same relationship. Does this mean that variables of type relationship collection cannot appear in the same path matching?
Relationship isomorphism
The same relationship cannot be returned more than once for each path matching record. Cypher makes use of relationship isomorphism for path matching.
Neo4j Cypher makes use of relationship isomorphism for path matching and is a very effective way of reducing the result set size and preventing infinite traversals.
So I tested this statement and it behaves exactly as documented:
neo4j@neo4j> match (v1)-[e]->(v2)-[e]-(v3) return p;
Cannot use the same relationship variable 'e' for multiple patterns (line 2, column 13 (offset: 14))
"match (v1)-[e]->(v2)-[e]-(v3) return p;"
But for the statement with the same semantic, or so I thought, I got different returns:
neo4j@neo4j> match p=(v1)-[e*1]->(v2)-[e*1]-(v3) return p;
+-------------------------------------------+
| p |
+-------------------------------------------+
| ({id: 2})-[:E]->({id: 1})<-[:E]-({id: 2}) |
| ({id: 3})-[:E]->({id: 1})<-[:E]-({id: 3}) |
| ({id: 4})-[:E]->({id: 1})<-[:E]-({id: 4}) |
| ({id: 1})-[:E]->({id: 2})<-[:E]-({id: 1}) |
| ({id: 1})-[:E]->({id: 3})<-[:E]-({id: 1}) |
| ({id: 1})-[:E]->({id: 4})<-[:E]-({id: 1}) |
| ({id: 4})-[:E]->({id: 4})-[:E]->({id: 4}) |
+-------------------------------------------+
So my question 1 is, how does it make sense that the two statements above get different results? If the comparison of the relationships ignores the direction, shouldn't statement `match (v1)-[e]->(v2)-[e]-(v3) return p` also report an error?
I also tested this statement:
neo4j@neo4j> match p=(v1)-[e*1]->(v2)-[e*2]-(v3) return p,length(p);
+---------------------------------------------------------------------------------------+
| p | length(p) |
+---------------------------------------------------------------------------------------+
| ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) | 4 |
| ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) | 4 |
| ({id: 4})-[:E]->({id: 4})<-[:E]-({id: 4})-[:E]->({id: 4})<-[:E]-({id: 1}) | 4 |
| ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) | 4 |
| ({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2}) | 4 |
| ({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3}) | 4 |
| ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) | 4 |
+---------------------------------------------------------------------------------------+
``As you can see, the same relationship returned more than once for each path matching record and the length of path is not as expected.
So question 2, is the result of this statement unexpected?
Similarly, such problems exist in directed edge patterns:
```
neo4j@neo4j> match p=(v1)-[e]->(v2)-[e]->(v3) return p,length(p);
Cannot use the same relationship variable 'e' for multiple patterns (line 2, column 15 (offset: 16))
"match p=(v1)-[e]->(v2)-[e]->(v3) return p,length(p);"
^
neo4j@neo4j> match p=(v1)-[e*1]->(v2)-[e*1]->(v3) return p,length(p);
+-------------------------------------------------------+
| p | length(p) |
+-------------------------------------------------------+
| ({id: 4})-[:E]->({id: 4})-[:E]->({id: 4}) | 2 |
+-------------------------------------------------------+
1 row available after 24 ms, consumed after another 0 ms
neo4j@neo4j> match p=(v1)-[e*1]->(v2)-[e*2]->(v3) return p,length(p);
+---------------------------------------------------------------------------------------+
| p | length(p) |
+---------------------------------------------------------------------------------------+
| ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) | 4 |
| ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) | 4 |
| ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) | 4 |
| ({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2}) | 4 |
| ({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3}) | 4 |
| ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) | 4 |
+---------------------------------------------------------------------------------------+
Question 3, do these statements behave as expected? What are the semantics of these statements?
---
I also tested some other statements:
```
neo4j@neo4j> match p=(v1)-[e*1..2]->(v2)-[e*2..4]->(v3) return length(p),p;
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| length(p) | p |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| 4 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 4 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 4 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 6 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 4 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 4 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 8 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 8 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 8 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 4 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 6 | ({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 6 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4}) |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
21 rows available after 31 ms, consumed after another 3 ms
neo4j@neo4j> match p1=(v1)-[e*1..2]->(v2) match p2=(v2)-[e*2..4]->(v3) return length(p1)+length(p2),p1,p2;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| length(p1)+length(p2) | p1 | p2 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 4 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1}) |
| 4 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1}) |
| 4 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 8 | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 6 | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1}) | ({id: 1})-[:E]->({id: 4})-[:E]->({id: 4})-[:E]->({id: 1}) |
| 4 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 2}) | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2}) | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2}) | ({id: 2})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 2}) |
| 8 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3}) | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 4 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 3}) | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 8 | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3}) | ({id: 3})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 3}) |
| 8 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4}) | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 2})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 8 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4}) | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 3})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 4 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 6 | ({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) | ({id: 4})-[:E]->({id: 4})-[:E]->({id: 1})-[:E]->({id: 4}) |
| 6 | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4}) | ({id: 4})-[:E]->({id: 1})-[:E]->({id: 4})-[:E]->({id: 4}) |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
21 rows available after 2 ms, consumed after another 7 ms
My question 4 is that are the above two statements semantically equivalent?
IMHO, the semantics of the last statement is clear and follows `relationship isomorphism` exactly.