From e63181f2c273ebd23b5c0679e0f5d6f25edba9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:03:26 +0200 Subject: [PATCH 01/10] text --- modules/ROOT/content-nav.adoc | 1 + modules/ROOT/images/match-modes-reference.svg | 9 + .../gql-conformance/supported-optional.adoc | 7 +- modules/ROOT/pages/clauses/match.adoc | 5 +- ...ions-additions-removals-compatibility.adoc | 39 +++ modules/ROOT/pages/patterns/index.adoc | 1 + modules/ROOT/pages/patterns/match-modes.adoc | 244 ++++++++++++++++ .../pages/patterns/non-linear-patterns.adoc | 5 +- modules/ROOT/pages/patterns/reference.adoc | 261 +++++++++++++++++- 9 files changed, 560 insertions(+), 12 deletions(-) create mode 100644 modules/ROOT/images/match-modes-reference.svg create mode 100644 modules/ROOT/pages/patterns/match-modes.adoc 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/match-modes-reference.svg b/modules/ROOT/images/match-modes-reference.svg new file mode 100644 index 000000000..43cfa73b7 --- /dev/null +++ b/modules/ROOT/images/match-modes-reference.svg @@ -0,0 +1,9 @@ + + + + + + + + + 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..0af84205e 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 by default 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..37bea914e 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -21,6 +21,45 @@ Replacement syntax for deprecated and removed features are also indicated. Cypher 25 was introduced in Neo4j 2025.06 and can only be used on Neo4j 2025.06+ databases. Features removed in Cypher 25 are still available on Neo4j 2025.06+ databases either by prepending a query with `CYPHER 5` or by having Cypher 5 as the default language for the database. +[[cypher-deprecations-additions-removals-2025.xx]] +== Neo4j 2025.xx + +=== New in Cypher 25 + +[cols="2", options="header"] +|=== +| Feature +| Details + +a| +label:functionality[] +label:new[] +[source, cypher, role="noheader"] +---- +MATCH REPEATABLE ELEMENTS p = (:B)->{,5}() +RETURN [n IN nodes(p) | n.q] AS nodes +---- + +a| +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 patterns can be repeatedly traversed. + +| +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, `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. + +|=== + [[cypher-deprecations-additions-removals-2025.06]] == Neo4j 2025.06 diff --git a/modules/ROOT/pages/patterns/index.adoc b/modules/ROOT/pages/patterns/index.adoc index c4b480a2e..53295d5dc 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 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..ff06bb87f --- /dev/null +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -0,0 +1,244 @@ +: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. +Cypher offers 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.xx] + +[[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 and return to the same starting location. + +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 the default match mode Cypher. +That is, if no match mode is selected, Cypher will default to solve graph patterns according to the restrictions imposed by `DIFFERENT RELATIONSHIPS`. + +[NOTE] +The `DIFFERENT RELATIONSHIPS` keyword was released in Neo4j 2025.xx 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 (`-\->`). + +.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> xref:expressions/list-expressions.adoc#list-comprehension[list comprehensions] iterating over nodes and relationships in a path and returning specific properties (the `name` property from nodes, and `id` 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. + +.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* +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> The xref:functions/predicate.adoc#functions-all[`all()`] function ensures that each bridge must be traversed once in the path. + +.Result +[source] +---- +(no results) +---- + +No results are returned because, when using the DIFFERENT RELATIONSHIPS match mode, it is impossible to traverse all 7 relationships once without any re-traversals, which is not allowed. + +For more information about this match mode, see xref:patterns/reference.adoc#match-modes-rules-different-relationships[Syntax & semantics -> `DIFFERENT RELATIONSHIPS`]. + +[role=label--new-2025.xx] +[[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öningsberg exactly once and returning to the starting location. +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 the MATCH. + +The following example re-runs the above query, matching paths where each Königsberg bridge is crossed before returning the starting location +However, this time the query uses the match mode `REPEATABLE ELEMENTS`. + +.Find a path traversing all 7 bridges at least once before returning to the starting `Location` using `REPEATABLE ELEMENTS` +[source, cypher] +---- +MATCH REPEATABLE ELEMENTS p = (start:Location {name: 'Kneiphof'})-[:BRIDGE]-{,9}(start) // <1> +WHERE all(bridge IN range(1,7) WHERE bridge IN [r IN relationships(p) | r.id]) +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. + +.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. + +Modifying the query testing Euler’s hypothesis using `REPEATABLE ELEMENTS` to instead count the total number of paths satisfying the condition of crossing every bridge at least once before returning to `Kneiphof` within `9` hops reveals a total of `1152` such paths. + +.Count the paths traversing all 7 bridges at least once using `REPEATABLE ELEMENTS` +[source, cypher] +---- +MATCH REPEATABLE ELEMENTS p = (start:Location {name: 'Kneiphof'})-[:BRIDGE]-{,9}(start) +WHERE all(bridge IN range(1,7) WHERE bridge IN [r IN relationships(p) | r.id]) +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..ade4bcd36 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1061,7 +1061,8 @@ 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 +1495,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 +1539,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 +1617,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.xx] + +[[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 must 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 two graph patterns 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.xx 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 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-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 used 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* Date: Wed, 11 Jun 2025 15:15:20 +0200 Subject: [PATCH 02/10] images --- .../images/different-relationships-graph.svg | 9 +++++ modules/ROOT/images/match-modes-graph.svg | 33 ++++++++++++++++ modules/ROOT/images/match-modes-reference.svg | 22 +++++++---- .../ROOT/images/repeatable-elements-graph.svg | 9 +++++ ...ions-additions-removals-compatibility.adoc | 39 ------------------- modules/ROOT/pages/patterns/match-modes.adoc | 7 ++++ 6 files changed, 72 insertions(+), 47 deletions(-) create mode 100644 modules/ROOT/images/different-relationships-graph.svg create mode 100644 modules/ROOT/images/match-modes-graph.svg create mode 100644 modules/ROOT/images/repeatable-elements-graph.svg diff --git a/modules/ROOT/images/different-relationships-graph.svg b/modules/ROOT/images/different-relationships-graph.svg new file mode 100644 index 000000000..68628b331 --- /dev/null +++ b/modules/ROOT/images/different-relationships-graph.svg @@ -0,0 +1,9 @@ + + + + + + + + + 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 index 43cfa73b7..9e856fa63 100644 --- a/modules/ROOT/images/match-modes-reference.svg +++ b/modules/ROOT/images/match-modes-reference.svg @@ -1,9 +1,15 @@ - - - - - - - - + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/repeatable-elements-graph.svg b/modules/ROOT/images/repeatable-elements-graph.svg new file mode 100644 index 000000000..b1f27ce33 --- /dev/null +++ b/modules/ROOT/images/repeatable-elements-graph.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 37bea914e..7cc7e4919 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -21,45 +21,6 @@ Replacement syntax for deprecated and removed features are also indicated. Cypher 25 was introduced in Neo4j 2025.06 and can only be used on Neo4j 2025.06+ databases. Features removed in Cypher 25 are still available on Neo4j 2025.06+ databases either by prepending a query with `CYPHER 5` or by having Cypher 5 as the default language for the database. -[[cypher-deprecations-additions-removals-2025.xx]] -== Neo4j 2025.xx - -=== New in Cypher 25 - -[cols="2", options="header"] -|=== -| Feature -| Details - -a| -label:functionality[] -label:new[] -[source, cypher, role="noheader"] ----- -MATCH REPEATABLE ELEMENTS p = (:B)->{,5}() -RETURN [n IN nodes(p) | n.q] AS nodes ----- - -a| -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 patterns can be repeatedly traversed. - -| -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, `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. - -|=== - [[cypher-deprecations-additions-removals-2025.06]] == Neo4j 2025.06 diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index ff06bb87f..d38f40c95 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -16,6 +16,8 @@ This match mode is required in order for paths to be able to traverse a relation 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 and return to the same starting location. +image::match-modes-graph.svg[Graph showing the seven bridges of Königsberg, width=400, role=popup] + To recreate the graph, run the following query against an empty Neo4j database: [source, cypher, role=test-setup] @@ -106,6 +108,8 @@ RETURN pathCount, 3+d|Rows: 1 |=== +image::different-relationships-graph.svg[Graph showing all but one of the seven bridges of Königsberg traversed, width=500, role=popup] +_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. @@ -195,6 +199,9 @@ RETURN [n IN nodes(p) | n.name] AS visitedLocations, The query now returns solutions, and the order of the bridges traversed in the path returned demonstrates that bridges `2` and `4` were crossed twice in order to return to `Kneiphof`. +image::repeatable-elements-graph.svg[Several graphs showing order of traversals when using repeatable elements match mode, width=500, role=popup] +_Sequence of bridge traversals when using `REPEATABLE ELEMENTS`._ + For more information about this match mode, see xref:patterns/reference.adoc#match-modes-rules-repeatable-elements[Syntax and semantics -> `REPEATABLE ELEMENTS`]. [[bounded-path-length]] From ec2a18ad89f1910626b25948daebef7337e0ba55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Wed, 11 Jun 2025 15:24:10 +0200 Subject: [PATCH 03/10] increase graph size --- modules/ROOT/pages/patterns/match-modes.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index d38f40c95..273398f64 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -16,7 +16,7 @@ This match mode is required in order for paths to be able to traverse a relation 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 and return to the same starting location. -image::match-modes-graph.svg[Graph showing the seven bridges of Königsberg, width=400, role=popup] +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: From e0efb322f949022177f60d2bb6bf50d3ef98163f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:26:46 +0200 Subject: [PATCH 04/10] editorial fixes --- modules/ROOT/images/match-modes-reference.svg | 9 ++-- modules/ROOT/pages/clauses/match.adoc | 2 +- ...ions-additions-removals-compatibility.adoc | 42 +++++++++++++++++++ modules/ROOT/pages/patterns/index.adoc | 2 +- modules/ROOT/pages/patterns/match-modes.adoc | 18 ++++---- modules/ROOT/pages/patterns/reference.adoc | 6 +-- 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/modules/ROOT/images/match-modes-reference.svg b/modules/ROOT/images/match-modes-reference.svg index 9e856fa63..1ef10fc09 100644 --- a/modules/ROOT/images/match-modes-reference.svg +++ b/modules/ROOT/images/match-modes-reference.svg @@ -1,11 +1,10 @@ - - - + + - + - + diff --git a/modules/ROOT/pages/clauses/match.adoc b/modules/ROOT/pages/clauses/match.adoc index 0af84205e..030457a2a 100644 --- a/modules/ROOT/pages/clauses/match.adoc +++ b/modules/ROOT/pages/clauses/match.adoc @@ -150,7 +150,7 @@ 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] -Cypher default match mode, `DIFFERENT RELATIONSHIPS`, will by default only match a relationship once inside a single pattern. +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] diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 7cc7e4919..9910c373a 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -21,6 +21,48 @@ Replacement syntax for deprecated and removed features are also indicated. Cypher 25 was introduced in Neo4j 2025.06 and can only be used on Neo4j 2025.06+ databases. Features removed in Cypher 25 are still available on Neo4j 2025.06+ databases either by prepending a query with `CYPHER 5` or by having Cypher 5 as the default language for the database. +[[cypher-deprecations-additions-removals-2025.xx]] +== Neo4j 2025.xx + +=== New in Cypher 25 + +[cols="2", options="header"] +|=== +| Feature +| Details + + +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 patterns 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. + +|=== + [[cypher-deprecations-additions-removals-2025.06]] == Neo4j 2025.06 diff --git a/modules/ROOT/pages/patterns/index.adoc b/modules/ROOT/pages/patterns/index.adoc index 53295d5dc..12d0faa4c 100644 --- a/modules/ROOT/pages/patterns/index.adoc +++ b/modules/ROOT/pages/patterns/index.adoc @@ -26,7 +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 which determine whether relationships can appear more than once in a graph pattern match. +* 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 index 273398f64..0172d48da 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -2,8 +2,8 @@ :table-caption!: = Match modes -Match modes determine whether relationships can appear more than once in a graph pattern match. -Cypher offers two 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 contains 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. @@ -14,7 +14,7 @@ This match mode is required in order for paths to be able to traverse a relation [[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 and return to the same starting location. +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. image::match-modes-graph.svg[Graph showing the seven bridges of Königsberg, width=600, role=popup] @@ -134,7 +134,7 @@ In the `DIFFERENT RELATIONSHIPS` match mode, each step must use a unique bridge. After the first step, one bridge is used, leaving 6 remaining bridges to be used in the subsequent steps. Once all 6 remaining bridges are traversed, a 7th 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 and returning to the same starting point. +This reflects the conclusion of Euler’s seven bridges of Königsberg problem: the impossibility of crossing each bridge exactly once. The below query demonstrates this impossibility. More specifically, it tries to find a path where each bridge is crossed exactly once with a length of `7` relationships, starting and ending at the same `Location`, `Kneiphof`. @@ -156,7 +156,7 @@ RETURN [n IN nodes(p) | n.name] AS visitedLocations, (no results) ---- -No results are returned because, when using the DIFFERENT RELATIONSHIPS match mode, it is impossible to traverse all 7 relationships once without any re-traversals, which is not allowed. +No results are returned because, when using the `DIFFERENT RELATIONSHIPS` match mode, it is impossible to traverse all 7 relationships once without any re-traversals, which is not allowed. For more information about this match mode, see xref:patterns/reference.adoc#match-modes-rules-different-relationships[Syntax & semantics -> `DIFFERENT RELATIONSHIPS`]. @@ -165,11 +165,11 @@ For more information about this match mode, see xref:patterns/reference.adoc#mat == 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öningsberg exactly once and returning to the starting location. +In so doing, the `REPEATABLE ELEMENTS` match mode does not solve the impossibility of crossing every bridge in Königsberg exactly once. 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 the MATCH. +Queries utilizing this match mode must specify the `REPEATABLE ELEMENTS` keyword after `MATCH`. The following example re-runs the above query, matching paths where each Königsberg bridge is crossed before returning the starting location However, this time the query uses the match mode `REPEATABLE ELEMENTS`. @@ -231,12 +231,12 @@ RETURN count(p) AS pathCount 1+d|Rows: 1 |=== -If the path length is increased to exactly `10`, a total of `5580` paths are returned, `11` returns `54144`, `12` returns `229824`, and so on, without limit. +If the path length is increased to exactly `10`, a total of `5580` paths are returned, `11` hops returns `54144` paths, `12` hops returns `229824` paths, and so on, without limit. To ensure that a `MATCH` will return a finite number of solutions in a finite amount of time, xref:patterns/reference.adoc#quantifiers-rules#quantifiers-rules[unbounded quantifiers] that do not impose an upper bound on a pattern, such as `*`, `+`, or `{1,}` are not allowed in combination with `REPEATABLE ELEMENTS`. Also, users should take into account that the number of results returned for a high number of repetitions can significantly impact both memory usage and the speed of the query. -.Not allowed: Find paths of an unbounded length using REPEATABLE ELEMENTS +.Not allowed: find paths of an unbounded length using `REPEATABLE ELEMENTS` [source, cypher, role=test-fail] ---- MATCH REPEATABLE ELEMENTS p = (start:Location {name: 'Kneiphof'})-[:BRIDGE]-+(start) diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index ade4bcd36..a3e2d5694 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1706,7 +1706,7 @@ This restriction is required to prevent a a potentially infinite number of retur [[match-modes-rules-clauses-subqueries]] ==== Clauses and subqueries -Match modes can only be used after `MATCH`. +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. @@ -1830,7 +1830,7 @@ The `DIFFERENT RELATIONSHIPS` match mode allows only nodes to recur in a path. .Match a pattern with a length of `5` relationships using the `DIFFERENT RELATIONSHIPS` match mode [source, cypher] ---- -MATCH p = (:B)->{5}() +MATCH p = (:B)-->{5}() RETURN [n IN nodes(p) | n.q] AS nodes ---- @@ -1850,7 +1850,7 @@ The `REPEATABLE ELEMENTS` match mode allows both nodes and relationships to be r .Match a pattern with a length of `5` relationships using the `REPEATABLE ELEMENTS` match mode [source, cypher] ---- -MATCH REPEATABLE ELEMENTS p = (:B)->{5}() +MATCH REPEATABLE ELEMENTS p = (:B)-->{5}() RETURN [n IN nodes(p) | n.q] AS nodes ---- From 5822372d96df814a4e084f3a420a0adb1b282d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:35:30 +0200 Subject: [PATCH 05/10] fix quantifier link --- modules/ROOT/pages/patterns/match-modes.adoc | 4 ++-- modules/ROOT/pages/patterns/reference.adoc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index 0172d48da..fdc1ad2b0 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -81,7 +81,7 @@ As the results show, a node may be traversed several times in the same path, but |=== 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, and the query returns one of those paths as a `samplePath`, showing both the nodes and relationships traversed therein. +It shows that there are `48` valid paths with this length, where no relationships (bridges) are re-traversed, and the query returns one of those paths as a `samplePath`, showing both the nodes and relationships traversed therein. .Find paths with a length of 6 relationships from a start node [source, cypher] @@ -233,7 +233,7 @@ RETURN count(p) AS pathCount If the path length is increased to exactly `10`, a total of `5580` paths are returned, `11` hops returns `54144` paths, `12` hops returns `229824` paths, and so on, without limit. -To ensure that a `MATCH` will return a finite number of solutions in a finite amount of time, xref:patterns/reference.adoc#quantifiers-rules#quantifiers-rules[unbounded quantifiers] that do not impose an upper bound on a pattern, such as `*`, `+`, or `{1,}` are not allowed in combination with `REPEATABLE ELEMENTS`. +To ensure that a `MATCH` will return a finite number of solutions in a finite amount of time, xref:patterns/reference.adoc#quantifiers-rules[unbounded quantifiers] that do not impose an upper bound on a pattern, such as `*`, `+`, or `{1,}` are not allowed in combination with `REPEATABLE ELEMENTS`. Also, users should take into account that the number of results returned for a high number of repetitions can significantly impact both memory usage and the speed of the query. .Not allowed: find paths of an unbounded length using `REPEATABLE ELEMENTS` diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index a3e2d5694..749a10dd5 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1695,7 +1695,7 @@ 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-rules[quantifiers] in different match modes: +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, }`, `{ , }`, `*`. From 6ed983b6f72177e1c61b2c7eda55b6391ada26dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 12 Jun 2025 10:43:50 +0200 Subject: [PATCH 06/10] 2025.06 --- ...ions-additions-removals-compatibility.adoc | 68 +++++++------------ modules/ROOT/pages/patterns/match-modes.adoc | 6 +- modules/ROOT/pages/patterns/reference.adoc | 4 +- 3 files changed, 31 insertions(+), 47 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 9910c373a..2b19bdce7 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -21,48 +21,6 @@ Replacement syntax for deprecated and removed features are also indicated. Cypher 25 was introduced in Neo4j 2025.06 and can only be used on Neo4j 2025.06+ databases. Features removed in Cypher 25 are still available on Neo4j 2025.06+ databases either by prepending a query with `CYPHER 5` or by having Cypher 5 as the default language for the database. -[[cypher-deprecations-additions-removals-2025.xx]] -== Neo4j 2025.xx - -=== New in Cypher 25 - -[cols="2", options="header"] -|=== -| Feature -| Details - - -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 patterns 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. - -|=== - [[cypher-deprecations-additions-removals-2025.06]] == Neo4j 2025.06 @@ -397,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 patterns 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/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index fdc1ad2b0..3c84f6f74 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -9,7 +9,7 @@ Cypher contains two match modes: 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.xx] +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 @@ -47,7 +47,7 @@ As such, `DIFFERENT RELATIONSHIPS` is ideal to showcase the Königsberg bridges That is, if no match mode is selected, Cypher will default to solve graph patterns according to the restrictions imposed by `DIFFERENT RELATIONSHIPS`. [NOTE] -The `DIFFERENT RELATIONSHIPS` keyword was released in Neo4j 2025.xx and can be used to explicitly specify Cypher's default match mode after `MATCH`. +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. @@ -160,7 +160,7 @@ No results are returned because, when using the `DIFFERENT RELATIONSHIPS` match For more information about this match mode, see xref:patterns/reference.adoc#match-modes-rules-different-relationships[Syntax & semantics -> `DIFFERENT RELATIONSHIPS`]. -[role=label--new-2025.xx] +[role=label--new-2025.06] [[repeatable-elements]] == REPEATABLE ELEMENTS diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index 749a10dd5..fdd390435 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1623,7 +1623,7 @@ MATCH ()-[r]->()-->(), ()-[r]-() 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.xx] +* xref:patterns/reference.adoc#match-modes-rules-repeatable-elements[`REPEATABLE ELEMENTS`] label:new[Introduced in Neo4j 2025.06] [[match-modes-syntax]] === Syntax @@ -1660,7 +1660,7 @@ 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.xx and can be used to explicitly specify Cypher's default match mode after `MATCH`. +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: From b50f439ca27537eac678c896987345335e4d6d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:44:40 +0200 Subject: [PATCH 07/10] new graphs --- .../images/different-relationships-graph.svg | 37 +++- .../ROOT/images/repeatable-elements-graph.svg | 172 +++++++++++++++++- modules/ROOT/pages/patterns/match-modes.adoc | 2 +- 3 files changed, 194 insertions(+), 17 deletions(-) diff --git a/modules/ROOT/images/different-relationships-graph.svg b/modules/ROOT/images/different-relationships-graph.svg index 68628b331..5941c706c 100644 --- a/modules/ROOT/images/different-relationships-graph.svg +++ b/modules/ROOT/images/different-relationships-graph.svg @@ -1,9 +1,30 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/images/repeatable-elements-graph.svg b/modules/ROOT/images/repeatable-elements-graph.svg index b1f27ce33..157b07922 100644 --- a/modules/ROOT/images/repeatable-elements-graph.svg +++ b/modules/ROOT/images/repeatable-elements-graph.svg @@ -1,9 +1,165 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index 3c84f6f74..9c74eed55 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -199,7 +199,7 @@ RETURN [n IN nodes(p) | n.name] AS visitedLocations, The query now returns solutions, and the order of the bridges traversed in the path returned demonstrates that bridges `2` and `4` were crossed twice in order to return to `Kneiphof`. -image::repeatable-elements-graph.svg[Several graphs showing order of traversals when using repeatable elements match mode, width=500, role=popup] +image::repeatable-elements-graph.svg[Several graphs showing order of traversals when using repeatable elements match mode, width=600, role=popup] _Sequence of bridge traversals when using `REPEATABLE ELEMENTS`._ For more information about this match mode, see xref:patterns/reference.adoc#match-modes-rules-repeatable-elements[Syntax and semantics -> `REPEATABLE ELEMENTS`]. From 7a4bbeafd01374c55951a1a8c791ed5095ef838d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 16 Jun 2025 11:03:04 +0200 Subject: [PATCH 08/10] post-review corrections --- .../ROOT/images/repeatable-elements-graph.svg | 228 ++++++++++-------- modules/ROOT/pages/patterns/match-modes.adoc | 95 ++++---- .../pages/patterns/non-linear-patterns.adoc | 3 +- modules/ROOT/pages/patterns/reference.adoc | 17 +- 4 files changed, 182 insertions(+), 161 deletions(-) diff --git a/modules/ROOT/images/repeatable-elements-graph.svg b/modules/ROOT/images/repeatable-elements-graph.svg index 157b07922..f85e06d7f 100644 --- a/modules/ROOT/images/repeatable-elements-graph.svg +++ b/modules/ROOT/images/repeatable-elements-graph.svg @@ -1,158 +1,158 @@ - - + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - - - + + + + + + + + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + @@ -162,4 +162,20 @@ + + + + + + + + + + + + + + + + diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index 9c74eed55..537677e57 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -3,7 +3,7 @@ = 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 contains two match modes: +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. @@ -14,7 +14,7 @@ This match mode is required in order for paths to be able to traverse a relation [[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. +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] @@ -43,8 +43,8 @@ The `DIFFERENT RELATIONSHIPS` match mode ensures that a relationship can only oc 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 the default match mode Cypher. -That is, if no match mode is selected, Cypher will default to solve graph patterns according to the restrictions imposed by `DIFFERENT RELATIONSHIPS`. +`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`. @@ -52,7 +52,7 @@ 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 (`-\->`). +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] @@ -62,9 +62,9 @@ RETURN [n IN nodes(p) | n.name] AS locations, [r IN relationships(p) | r.id] AS crossedBridges // <1> ---- -<1> xref:expressions/list-expressions.adoc#list-comprehension[list comprehensions] iterating over nodes and relationships in a path and returning specific properties (the `name` property from nodes, and `id` from relationships). +<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. +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 `[7, 2, 5, 7, 2]`, 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* -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> The xref:functions/predicate.adoc#functions-all[`all()`] function ensures that each bridge must be traversed once in the path. - -.Result -[source] ----- -(no results) ----- - -No results are returned because, when using the `DIFFERENT RELATIONSHIPS` match mode, it is impossible to traverse all 7 relationships once without any re-traversals, 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 this match mode, see xref:patterns/reference.adoc#match-modes-rules-different-relationships[Syntax & semantics -> `DIFFERENT RELATIONSHIPS`]. @@ -165,26 +143,52 @@ For more information about this match mode, see xref:patterns/reference.adoc#mat == 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 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 example re-runs the above query, matching paths where each Königsberg bridge is crossed before returning the starting location -However, this time the query uses the match mode `REPEATABLE ELEMENTS`. +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]) -WITH p ORDER BY length(p) LIMIT 1 +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 + [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*(lds) ---- -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. +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: diff --git a/modules/ROOT/pages/patterns/reference.adoc b/modules/ROOT/pages/patterns/reference.adoc index fdd390435..2cf0114ff 100644 --- a/modules/ROOT/pages/patterns/reference.adoc +++ b/modules/ROOT/pages/patterns/reference.adoc @@ -1061,7 +1061,8 @@ RETURN a = c, b = d, size(r) |=== -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. +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: @@ -1644,19 +1645,19 @@ matchMode ::= ==== DIFFERENT RELATIONSHIPS `DIFFERENT RELATIONSHIPS` is a restrictive match mode. -It requires that all relationships matched across all constituent path patterns in a graph pattern must be unique. More specifically: +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 two graph patterns cannot return paths: +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)-[f]-(c)-[r]-(d) // r repeated twice MATCH (a)-[r]-(b), (c)-[r]-(d) // r repeated twice ---- @@ -1666,7 +1667,7 @@ For example, the following two `MATCH` clauses are equivalent: [source, role=noheader] ---- -MATCH (a)--{2}(b), +MATCH (a)--{2}(b) MATCH DIFFERENT RELATIONSHIPS (a)--{2}(b) ---- @@ -1684,11 +1685,11 @@ More specifically: 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 can return paths: +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)-[f]-(c)-[r]-(d) // r repeated twice MATCH REPEATABLE ELEMENTS (a)-[r]-(b), (c)-[r]-(d) // r repeated twice ---- From 8a61f70cabe829adbaa02349e9e1dd9bd1dce257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 16 Jun 2025 12:03:47 +0200 Subject: [PATCH 09/10] minor correction --- .../pages/deprecations-additions-removals-compatibility.adoc | 2 +- modules/ROOT/pages/patterns/match-modes.adoc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc index 2b19bdce7..4da92e540 100644 --- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc +++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc @@ -366,7 +366,7 @@ 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 patterns can be repeatedly traversed. +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[] diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index 537677e57..73adbce44 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -81,7 +81,8 @@ As the results show, a node may be traversed several times in the same path, but |=== 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, and the query returns one of those paths as a `samplePath`, showing both the nodes and relationships traversed therein. +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. .Find paths with a length of 6 relationships from a start node [source, cypher] @@ -132,7 +133,7 @@ RETURN count(p) AS pathCount In the `DIFFERENT RELATIONSHIPS` match mode, 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. -Once six remaining bridges are traversed, a seventh step would require re-traversing a bridge, which is not allowed. +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. From 814244504da26665668c95d53573f0f6eed5028d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Pryce-=C3=85klundh?= <112686610+JPryce-Aklundh@users.noreply.github.com> Date: Mon, 16 Jun 2025 12:08:42 +0200 Subject: [PATCH 10/10] path fix --- modules/ROOT/pages/patterns/match-modes.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/pages/patterns/match-modes.adoc b/modules/ROOT/pages/patterns/match-modes.adoc index 73adbce44..0385bd384 100644 --- a/modules/ROOT/pages/patterns/match-modes.adoc +++ b/modules/ROOT/pages/patterns/match-modes.adoc @@ -64,7 +64,7 @@ RETURN [n IN nodes(p) | n.name] AS locations, <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 `[7, 2, 5, 7, 2]`, which traverses the same bridge more than once, cannot be matched using the `DIFFERENT RELATIONSHIPS` match mode). +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*