diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc index 5b1425487..dee0772e5 100644 --- a/modules/ROOT/content-nav.adoc +++ b/modules/ROOT/content-nav.adoc @@ -52,6 +52,7 @@ ** xref:patterns/variable-length-patterns.adoc[] ** xref:patterns/shortest-paths.adoc[] ** xref:patterns/non-linear-patterns.adoc[] +** xref:patterns/match-modes.adoc[] ** xref:patterns/reference.adoc[] * xref:values-and-types/index.adoc[] diff --git a/modules/ROOT/images/different-relationships-graph.svg b/modules/ROOT/images/different-relationships-graph.svg new file mode 100644 index 000000000..5941c706c --- /dev/null +++ b/modules/ROOT/images/different-relationships-graph.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/match-modes-graph.svg b/modules/ROOT/images/match-modes-graph.svg new file mode 100644 index 000000000..8080953b3 --- /dev/null +++ b/modules/ROOT/images/match-modes-graph.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/match-modes-reference.svg b/modules/ROOT/images/match-modes-reference.svg new file mode 100644 index 000000000..1ef10fc09 --- /dev/null +++ b/modules/ROOT/images/match-modes-reference.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/repeatable-elements-graph.svg b/modules/ROOT/images/repeatable-elements-graph.svg new file mode 100644 index 000000000..f85e06d7f --- /dev/null +++ b/modules/ROOT/images/repeatable-elements-graph.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc index 9ae3c2f56..81c37ee40 100644 --- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc +++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc @@ -15,9 +15,14 @@ These codes order the features in the table below. | G002 | Different-edges match mode -| xref:patterns/reference.adoc#graph-patterns-rules-relationship-uniqueness[Relationship uniqueness in Cypher] +| xref:patterns/match-modes.adoc#different-relationships[`DIFFERENT RELATIONSHIPS`] | The semantic for this feature is the default Cypher semantic. +| G003 +| Explicit `REPEATABLE ELEMENTS` keyword +| xref:patterns/match-modes.adoc#repeatable-elements[`REPEATABLE ELEMENTS`] +| + | G004 | Path variables | xref:patterns/reference.adoc#path-patterns[Path patterns] diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index c0b8bc440..030457a2a 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -150,8 +150,9 @@ Unlike a node pattern, a relationship pattern cannot be used in a `MATCH` clause For more information about relationship patterns, see xref:patterns/fixed-length-patterns#relationship-patterns[Patterns -> Relationship patterns]. [NOTE] -Relationships will only be matched once inside a single pattern. -Read more about this behavior in the section on xref::patterns/reference.adoc#graph-patterns-rules-relationship-uniqueness[relationship uniqueness]. +Cypher default match mode, `DIFFERENT RELATIONSHIPS`, will only match a relationship once inside a single pattern. +The same is not true for the `REPEATABLE ELEMENTS` match mode. +For more information, see xref::patterns/match-modes.adoc[Match modes] [[empty-relationship-patterns]] === Empty relationship patterns diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 7cc7e4919..4da92e540 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -355,6 +355,32 @@ RETURN prop ---- | The keyword `ALL` can now be added after a xref:clauses/with.adoc#with-all-results[WITH] as the explicit form of a `WITH` without duplicate removal. +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +MATCH REPEATABLE ELEMENTS p = (:B)-->{,5}() +RETURN [n IN nodes(p) \| n.q] AS nodes +---- + +| +New match mode, xref:patterns/match-modes.adoc#repeatable-elements[`REPEATABLE ELEMENTS`]. +This is a non-restrictive match mode, in which relationships matched across all constituent path patterns in a graph pattern can be repeatedly traversed. + +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +MATCH DIFFERENT RELATIONSHIPS p = (:B)-->{,5}() +RETURN [n IN nodes(p) \| n.q] AS nodes +---- + +a| +New keyword, xref:patterns/match-modes.adoc#different-relationships[`DIFFERENT RELATIONSHIPS`], which enables explicitly specifying Cypher's default mode. +This is a restrictive match mode, which requires that all relationships matched across all constituent path patterns in a graph pattern must be unique. +Specifying `DIFFERENT RELATIONSHIPS` is functionally equivalent to not specifying a match mode. |=== diff --git a/modules/ROOT/pages/patterns/index.adoc b/modules/ROOT/pages/patterns/index.adoc index c4b480a2e..12d0faa4c 100644 --- a/modules/ROOT/pages/patterns/index.adoc +++ b/modules/ROOT/pages/patterns/index.adoc @@ -26,6 +26,7 @@ This chapter includes the following sections: * xref:patterns/variable-length-patterns.adoc[] - information about quantified path patterns, quantified relationships, and group variables. * xref:patterns/shortest-paths.adoc[] - information about finding the `SHORTEST` path patterns. * xref:patterns/non-linear-patterns.adoc[] - information about equijoins and graph patterns (combined path patterns). +* xref:patterns/match-modes.adoc[] - information about Cypher's different match modes, which determine whether relationships can appear more than once in a graph pattern match. * xref:patterns/reference.adoc[] - a reference for looking up the syntax and semantics of graph pattern matching. The model data in the examples used in this chapter are based on the UK national rail network, using https://www.raildeliverygroup.com/our-services/rail-data/fares-timetable-data.html[publicly available datasets]. diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc new file mode 100644 index 000000000..0385bd384 --- /dev/null +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -0,0 +1,255 @@ +:description: Information about Cypher's different match modes, which determine whether relationships can appear more than once in a graph pattern match. +:table-caption!: += Match modes + +Match modes determine whether relationships can appear more than once in a graph pattern match (nodes can appear multiple times regardless of the match mode). +Cypher supports two match modes: + +* xref:patterns/match-modes.adoc#different-relationships[`DIFFERENT RELATIONSHIPS`]: a relationship can only be traversed once in a given match for a graph pattern. +The same restriction does not hold for nodes, which may be re-traversed any number of times in a matched path. +This is Cypher’s default match mode, applicable to most use cases. +* xref:patterns/match-modes.adoc#repeatable-elements[`REPEATABLE ELEMENTS`]: no restrictions on how often nodes and relationships can be traversed in a match for a graph pattern. +This match mode is required in order for paths to be able to traverse a relationship more than once. label:new[Introduced in Neo4j 2025.06] + +[[example-graph]] +== Example graph + +To explain match modes, this page will use the scenario of the link:https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg[Seven bridges of Königsberg], a problem studied by link:https://en.wikipedia.org/wiki/Leonhard_Euler[Leonhard Euler] in 1736 to determine if one could cross all seven bridges of Königsberg exactly once in a single walk. + +image::match-modes-graph.svg[Graph showing the seven bridges of Königsberg, width=600, role=popup] + +To recreate the graph, run the following query against an empty Neo4j database: + +[source, cypher, role=test-setup] +---- +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) +---- + +[[different-relationships]] +== DIFFERENT RELATIONSHIPS + +The `DIFFERENT RELATIONSHIPS` match mode ensures that a relationship can only occur once for a given xref:clauses/match.adoc[`MATCH`] result, regardless of the direction it is traversed in. +The same restriction does not apply to nodes, which may be re-traversed any number of times in a match. +As such, `DIFFERENT RELATIONSHIPS` 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. + +`DIFFERENT RELATIONSHIPS` is Cypher's default match mode. +That is, if no match mode is specified, Cypher will default to solving graph patterns according to the restrictions imposed by `DIFFERENT RELATIONSHIPS`. + +[NOTE] +The `DIFFERENT RELATIONSHIPS` keyword was released in Neo4j 2025.06 and can be used to explicitly specify Cypher's default match mode after `MATCH`. +For example, `MATCH DIFFERENT RELATIONSHIPS p = (start)--{,2}(end)`. +This is functionally equivalent to not specifying a match mode. + +To show the behavior of `DIFFERENT RELATIONSHIPS`, consider the following query, which uses a xref:patterns/variable-length-patterns.adoc#quantified-relationships[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]\->`). + +.Find paths with a length of 5 relationships from a start node +[source, cypher] +---- +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 xref:expressions/list-expressions.adoc#list-comprehension[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). + +.Result +[role="queryresult",options="header,footer",cols="2* +ORDER BY pathCount +RETURN pathCount, + [n IN nodes(samplePath) | n.name] AS samplePathLocations, + [r IN relationships(samplePath) | r.id] AS samplePathBridges +---- + +<1> The xref:functions/list.adoc#functions-collect[`collect()`] function collects all paths and `[0]` takes the first entry as the `samplePath`. + +.Result +[role="queryresult",options="header,footer",cols="3* `DIFFERENT RELATIONSHIPS`]. + +[role=label--new-2025.06] +[[repeatable-elements]] +== REPEATABLE ELEMENTS + +The `REPEATABLE ELEMENTS` match mode ensures that there are no restrictions on how many times a node or relationship can occur for a given `MATCH` result. +In so doing, the `REPEATABLE ELEMENTS` match mode does not solve the impossibility of crossing every bridge in Königsberg exactly once in a single walk. +However, the ability to re-traverse relationships does allow Cypher to return paths when testing Euler’s hypothesis. + +[NOTE] +Queries utilizing this match mode must specify the `REPEATABLE ELEMENTS` keyword after `MATCH`. + +The following query matches the graph for paths with a length of `7` relationships using `REPEATABLE ELEMENTS` and returns a sample path. + +.Find a path with a length of 7 relationships using `REPEATABLE ELEMENTS` +[source, cypher] +---- +MATCH REPEATABLE ELEMENTS p = (:Location {name: 'Kneiphof'})-[:BRIDGE]-{7}() +WITH collect(p)[0] AS samplePath +RETURN [n IN nodes(samplePath) | n.name] AS samplePathLocations, + [r IN relationships(samplePath) | r.id] AS samplePathBridges +---- + +.Result +[role="queryresult",options="header,footer",cols="2* +WHERE all(bridge IN range(1,7) WHERE bridge IN [r IN relationships(p) | r.id]) // <2> +WITH p +ORDER BY length(p) +LIMIT 1 +RETURN [n IN nodes(p) | n.name] AS visitedLocations, + [r IN relationships(p) | r.id] AS crossedBridges +---- + +<1> Paths with a length of less than 9 relationships return no results because they do not allow enough moves to traverse all seven bridges at least once while forming a cycle back to Kneiphof. +<2> The xref:functions/predicate.adoc#functions-all[`all()`] function ensures that each bridge must be traversed once in the path. + +.Result +[role="queryresult",options="header,footer",cols="2* `REPEATABLE ELEMENTS`]. + +[[bounded-path-length]] +=== Bounded path length + +When using `DIFFERENT RELATIONSHIPS`, the number of returned paths is limited because relationships cannot be re-traversed. +However, because `REPEATABLE ELEMENTS` allows for re-traversing relationships, it enables full cycle re-traversals and paths that can double back on relationships. +As a result, `REPEATABLE ELEMENTS` can generate a very large, or even infinite, number of valid paths. + +The below query shows that there are `10583` valid paths with a length of `7` relationships starting from `Kneiphof` using `REPEATABLE ELEMENTS`: + +.Count the paths traversing all 7 bridges at least once using `REPEATABLE ELEMENTS` +[source, cypher] +---- +MATCH REPEATABLE ELEMENTS p = (:Location {name: 'Kneiphof'})-[:BRIDGE]-{7}() +RETURN count(p) AS pathCount +---- + +.Result +[role="queryresult",options="header,footer",cols="1*(lds) ---- -Note that as Cypher only allows a relationship to be traversed once in a given match for a graph pattern, the first and second legs are guaranteed to be different train services. -(See xref::patterns/reference.adoc#graph-patterns-rules-relationship-uniqueness[relationship uniqueness] for more details.) +Cypher's default match mode, `DIFFERENT RELATIONSHIPS`, only allows a relationship to be traversed once in a given match for a graph pattern. +(The same is not true for the `REPEATABLE ELEMENTS` match mode. +For more information, see xref::patterns/match-modes.adoc[Match modes]). +As a result, the first and second legs are guaranteed to be different train services. Similarly, another quantified relationship that bridges the stops calling at `Leeds` station and `Huddersfield` station is added: [source, role="noheader"] diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 9dfaad76f..2cf0114ff 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1061,7 +1061,9 @@ RETURN a = c, b = d, size(r) |=== -Because Cypher only allows paths to traverse a relationship once (see xref:patterns/reference.adoc#graph-patterns-rules-relationship-uniqueness[relationship uniqueness]), repeating a variable-length relationship in the same graph pattern will yield no results. +Because Cypher's default match mode, `DIFFERENT RELATIONSHIPS`, only allows paths to traverse a relationship once, repeating a variable-length relationship in the same graph pattern will yield no results. +(The same is not true for the `REPEATABLE ELEMENTS` match mode. +For more information, see xref::patterns/match-modes.adoc[Match modes]). For example, this `MATCH` clause will never pass on any intermediate results to subsequent clauses: [source, role=noheader] @@ -1494,6 +1496,7 @@ MATCH allShortestPaths((:A)-[:R*0..10]->(:B)) A graph pattern is a comma separated list of one or more path patterns. It is the top level construct provided to `MATCH`. +Whether or not a graph pattern can match a relationship more than once is governed by the selected xref:patterns/reference.adoc#match-modes[match mode]. image::patterns-graph-pattern-reference.svg[Cypher example of a graph pattern including path patterns,width=600,role=popup] @@ -1537,12 +1540,6 @@ Outside of that quantified path pattern, it must be treated as a group variable. (n)-[r]->+(m WHERE r.p = m.q) ---- -[[graph-patterns-rules-relationship-uniqueness]] -==== Relationship uniqueness - -A relationship can only be traversed once in a given match for a graph pattern. -The same restriction doesn't hold for nodes, which may be re-traversed any number of times in a match. - [[graph-patterns-rules-equijoin]] ==== Equijoin @@ -1621,6 +1618,257 @@ The repetition of a relationship variable in the following yields no solutions d MATCH ()-[r]->()-->(), ()-[r]-() ---- +[[match-modes]] +== Match modes + +A match mode specifies whether or not a relationship can be matched more than once when matching graph patterns. Cypher contains two match modes: + +* xref:patterns/reference.adoc#match-modes-rules-different-relationships[`DIFFERENT RELATIONSHIPS`] (default) +* xref:patterns/reference.adoc#match-modes-rules-repeatable-elements[`REPEATABLE ELEMENTS`] label:new[Introduced in Neo4j 2025.06] + +[[match-modes-syntax]] +=== Syntax + +[source, role=noheader] +---- +graphPattern ::= + [ matchMode ] pathPattern [ "," pathPattern ]* [ graphPatternWhereClause ] + +matchMode ::= + { REPEATABLE ELEMENT[S] | DIFFERENT RELATIONSHIPS } +---- + +[[match-modes-rules]] +=== Rules + +[[match-modes-rules-different-relationships]] +==== DIFFERENT RELATIONSHIPS + +`DIFFERENT RELATIONSHIPS` is a restrictive match mode. +It requires that all relationships matched across all constituent path patterns in a graph pattern be unique. +More specifically: + +* A relationship may only occur once for a given `MATCH` result. +* A given relationship can only be bound to at most one relationship variable (e.g. `-[r]-`) or an anonymous relationship pattern (`-[]-`). +* A relationship can only be bound once within a relationship xref:patterns/reference.adoc#quantified-path-patterns-rules-group-variables[group variable]. + +No solutions can be returned if a relationship variable occurs more than once across a graph pattern. +For example, the following patterns, where the `r` variable acts as an xref:patterns/reference.adoc#graph-patterns-rules-equijoin[equijoin] requiring all occurrences to match the same relationship, cannot return paths: + +[source, role=noheader] +---- +MATCH (a)-[r]-(b)-[f]-(c)-[r]-(d) // r repeated twice +MATCH (a)-[r]-(b), (c)-[r]-(d) // r repeated twice +---- + +The `DIFFERENT RELATIONSHIPS` keyword was released in Neo4j 2025.06 and can be used to explicitly specify Cypher's default match mode after `MATCH`. +Specifying the `DIFFERENT RELATIONSHIPS` keyword is functionally equivalent to not specifying a match mode. +For example, the following two `MATCH` clauses are equivalent: + +[source, role=noheader] +---- +MATCH (a)--{2}(b) +MATCH DIFFERENT RELATIONSHIPS (a)--{2}(b) +---- + +[[match-modes-rules-repeatable-elements]] +==== REPEATABLE ELEMENTS + +`REPEATABLE ELEMENTS` is a non-restrictive match mode. +It allows for relationships matched across all constituent path patterns in a graph pattern to be repeatedly traversed. +More specifically: + +* A relationship may occur more than once for a given `MATCH` result. +* A given relationship can be bound to more than one relationship variable or anonymous relationship pattern. +* A relationship can be bound more than once within a relationship group variable. + +Queries utilizing this match mode must add the keyword `REPEATABLE ELEMENTS` between the `MATCH` clause and the graph pattern. + +Solutions can be returned if a relationship variable occurs more than once across a graph pattern. +For example, the following two graph patterns, where the `r` variable acts as an xref:patterns/reference.adoc#graph-patterns-rules-equijoin[equijoin] requiring all occurrences to match the same relationship, can return paths: + +[source, role=noheader] +---- +MATCH REPEATABLE ELEMENTS (a)-[r]-(b)-[f]-(c)-[r]-(d) // r repeated twice +MATCH REPEATABLE ELEMENTS (a)-[r]-(b), (c)-[r]-(d) // r repeated twice +---- + +[[match-modes-rules-quantifier-bounds]] +==== Quantifier bounds + +The following applies to the use of variable-length patterns xref:patterns/reference.adoc#quantifiers-rules[quantifiers] in different match modes: + +* `DIFFERENT RELATIONSHIPS` does not require an upper bound on a quantifier. +The following are valid: `+`, `{n, }`, `{ , }`, `*`. +* `REPEATABLE ELEMENTS` requires all quantifiers to have an upper bound. +The following are not valid: `+`, `{n, }`, `{ , }`, `*`, but these are valid: `\{n}`, `{n, m}`, `{,m}`. +This restriction is required to prevent a a potentially infinite number of returned paths. + +[[match-modes-rules-clauses-subqueries]] +==== Clauses and subqueries + +Match modes can only be specified after `MATCH`. +They cannot be applied to a xref:clauses/merge.adoc[`MERGE`] clause. + +Match modes are allowed in the xref:subqueries/collect.adoc[`COLLECT`], xref:subqueries/count.adoc[`COUNT`], and xref:subqueries/existential.adoc[`EXISTS`] subqueries after a `MATCH` clause. +If so, the match mode applies to patterns matched within the subquery and is separate from that applied to the top level graph pattern. +In the following example, `REPEATABLE ELEMENTS` only applies to the pattern matched within the `COUNT` subquery: + +[source, role=noheader] +---- +MATCH (a)-[:R]->(b) +WHERE COUNT { + MATCH REPEATABLE ELEMENTS (a)-[:S]-{,10}(b) + RETURN * +} > 5 +RETURN * +---- + +[[match-modes-rules-selective-path-selectors]] +==== Selective path selectors + +The following applies to match modes and the number of path patterns with xref:patterns/reference.adoc#shortest-paths-rules-selective[selective path selectors] (`SHORTEST k`, `SHORTEST k GROUPS`, `ALL SHORTEST`, and `ANY k`). + +* If the match mode is `DIFFERENT RELATIONSHIPS`, there can only be one path pattern if it has a selective path selector. +* If the match mode is `REPEATABLE ELEMENTS`, there can be multiple path patterns even if one or more have a selective path selector. + +.Allowed: `DIFFERENT RELATIONSHIPS` with selective path selector and one path pattern +[source] +---- +MATCH SHORTEST 2 ((a)--(b) WHERE a.p < b.p)+ +---- + + +.Allowed: `REPEATABLE ELEMENTS` with multiple path patterns and selective path selectors +[source] +---- +MATCH REPEATABLE ELEMENTS SHORTEST 2 (x) ((a)--(b) WHERE a.p < b.p){,10}, + ANY (x)-->{,10}(:X) +---- + +.Not allowed: `DIFFERENT RELATIONSHIPS` with more than one path pattern and a selective path selector +[source] +---- +MATCH ALL SHORTEST (x) ((a)--(b) WHERE a.p < b.p){,10}, + ANY (x)-->{,10}(:X) +---- + + +[[match-modes-examples]] +=== Examples + +//// +[source, cypher, role=test-setup] +---- +MATCH (n) +DETACH DELETE n +---- +//// + +This section uses the following graph: + +image::match-modes-reference.svg[width=400, role=popup] + +To recreate it, run the following query against an empty Neo4j database: + +[source, cypher, role=test-setup] +---- +CREATE (n1:A {q: 1}), + (n2:B {q: 2}), + (n3:A {q: 3}), + (n4:A {q: 4}), + + (n1)-[:R]->(n2), + (n2)-[:R]->(n3), + (n3)-[:R]->(n2), + (n2)-[:R]->(n4), + (n4)-[:R]->(n1) +---- + +To demonstrate the basic concept behind `REPEATABLE ELEMENTS`, and how it differs from the `DIFFERENT RELATIONSHIPS` match mode, consider the following pattern, which attempts to form a relationship equijoin: `(a)-[r]-(b)-[r]-(c)`. +For this pattern to return any results, the same relationship must be re-traversed. +That is, the same relationship connecting `a` to `b` must be the same as that connecting `b` to `c`. + +If tested using `DIFFERENT RELATIONSHIPS`, no results are returned due to the restrictions of the match mode. + +.Find paths re-traversing the same relationship using `DIFFERENT RELATIONSHIPS` +[source, cypher] +---- +MATCH p = (:A)-[r]-(:B)-[r]-(:A) +RETURN [n IN nodes(p) | n.q] AS nodes +---- + +.Result +[source] +---- +(no results) +---- + +However, if the same query uses the `REPEATABLE ELEMENTS` match mode, four paths are returned in which the same relationship is traversed more than once. + +.Find paths re-traversing the same relationship using `REPEATABLE ELEMENTS` +[source, cypher] +---- +MATCH REPEATABLE ELEMENTS p = (:A)-[r]-(:B)-[r]-(:A) +RETURN [n IN nodes(p) | n.q] AS nodes +---- + +.Result +[role="queryresult",options="header,footer",cols="1*{5}() +RETURN [n IN nodes(p) | n.q] AS nodes +---- + +.Result +[role="queryresult",options="header,footer",cols="1*{5}() +RETURN [n IN nodes(p) | n.q] AS nodes +---- + +.Result +[role="queryresult",options="header,footer",cols="1*