Paths with unique relationships
By default Cypher® does not allow the same relationship to be traversed more than once in a given MATCH result, regardless of the direction it is traversed in.
The same restriction does not hold for nodes, which may be re-traversed any number of times in a matched path.
|
Cypher’s default pattern matching behavior can be explicitly specified using the
|
Example graph
To explain Cypher’s default behavior, which allows for the re-traversal of nodes but not relationships in the same MATCH result, this page will use the scenario of the Seven bridges of Königsberg, a problem studied by Leonhard Euler in 1736 to determine if one could cross all seven bridges of Königsberg exactly once in a single walk.
To recreate the graph, run the following query against an empty Neo4j database:
CREATE (kneiphof:Location {name: "Kneiphof"}),
(northBank:Location {name: "North Bank"}),
(southBank:Location {name: "South Bank"}),
(lomse:Location {name: "Lomse"}),
(kneiphof)-[:BRIDGE {id: 1}]->(northBank),
(kneiphof)-[:BRIDGE {id: 6}]->(southBank),
(kneiphof)-[:BRIDGE {id: 7}]->(lomse),
(northBank)-[:BRIDGE {id: 5}]->(kneiphof),
(northBank)-[:BRIDGE {id: 2}]->(lomse),
(southBank)-[:BRIDGE {id: 4}]->(kneiphof),
(southBank)-[:BRIDGE {id: 3}]->(lomse)
Cypher’s default traversal rules and the Königsberg bridges problem
Cypher’s default MATCH behavior is ideal to showcase the Königsberg bridges problem: in the graph model, not traversing a relationship means not traversing a bridge, the problem’s key constraint.
Consider the following query, which uses a quantified relationship to search for paths exactly 5 hops away from the start Location node, Kneiphof.
The relationships used in this query are directional, meaning paths are traversed following specific directions for each bridge (-[:BRIDGE]->).
MATCH p = (:Location {name: 'Kneiphof'})-[:BRIDGE]->{5}()
RETURN [n IN nodes(p) | n.name] AS locations,
[r IN relationships(p) | r.id] AS crossedBridges (1)
| 1 | The list comprehensions iterate over nodes and relationships in a path and return specific properties (the name property from nodes, and the id property from relationships). |
As the results show, a node may be traversed several times in the same path, but a relationship (bridge) is never re-traversed (for example, the path [6, 4, 1, 5, 6], which traverses the same bridge more than once, cannot be matched using the DIFFERENT RELATIONSHIPS match mode).
| locations | crossedBridges |
|---|---|
|
|
|
|
Rows: 2 |
|
In the next example, the direction is removed from the pattern, and the path length is increased to 6.
It shows that there are 48 valid paths with this length, where no relationships (bridges) are re-traversed.
The query returns one of those paths as a samplePath, showing both the nodes and relationships traversed therein.
MATCH p = (:Location {name: 'Kneiphof'})-[:BRIDGE]-{6}()
WITH count(p) AS pathCount, collect(p)[0] AS samplePath (1)
ORDER BY pathCount
RETURN pathCount,
[n IN nodes(samplePath) | n.name] AS samplePathLocations,
[r IN relationships(samplePath) | r.id] AS samplePathBridges
| 1 | The collect() function collects all paths and [0] takes the first entry as the samplePath. |
| pathCount | samplePathLocations | samplePathBridges |
|---|---|---|
|
|
|
Rows: 1 |
||
In the samplePath with a length of 6 returned by DIFFERENT RELATIONSHIPS, all bridges are traversed except for bridge 3.
However, if the relationship count is increased to 7, 0 paths are returned.
MATCH p = (:Location {name: 'Kneiphof'})--{7}()
RETURN count(p) AS pathCount
| pathCount |
|---|
|
Rows: 1 |
Using Cypher’s default MATCH behavior, each step must use a unique bridge.
After the first step, one bridge is used, leaving six remaining bridges to be used in the subsequent steps.
After the sixth bridge is traversed, a seventh step would require re-traversing a bridge, which is not allowed.
This reflects the conclusion of Euler’s Seven bridges of Königsberg problem: the impossibility of crossing each bridge exactly once in a single walk.
For more information about Cypher’s default MATCH behavior, see Syntax & semantics → Match modes.
Non-default MATCH behavior
Cypher’s default MATCH behavior is applicable to most use cases.
It is, however, possible to alter how paths are traversed to solve specific problems, either by permitting re-traversal of relationships using REPEATABLE ELEMENTS or by not allowing the re-traversal of nodes in the same path with the ACYCLIC keyword.
For more information, see: