Skip to content

Commit 7af0652

Browse files
Document lower bound restriction for shortestPath() and allShortestPath() functions (#1146)
Document that the shortestPath() and allShortestPath() functions can only have a lower bound of 0 or 1 for its variable length pattern. This is not allowed: ` MATCH p=shortestPath((a:A)-[:R*2..]->(b:B)) RETURN 1` A lower bound can be specified using a filter, but might lead to executing a possibly very slow fallback plan. ` MATCH p=shortestPath((a:A)-[:R*]->(b:B)) WHERE length(p)>2 RETURN 1` The possibly very slow fallback plan is this part: ``` | | +Top | 3 | anon_1 ASC LIMIT 1 | 1 | In Pipeline 6 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +Projection | 4 | length(p) AS anon_1 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Filter | 5 | length(p) > $autoint_0 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Projection | 6 | (a)-[anon_0*]->(b) AS p | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +VarLengthExpand(Into) | 7 | (a)-[anon_0:R*]->(b) | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 8 | a, b | 100 | Fused in Pipeline 5 | | | +----+-------------------------------------------------------+----------------+---------------------+ ``` Within this query plan: ``` +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ | Operator | Id | Details | Estimated Rows | Pipeline | +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ | +ProduceResults | 0 | `1` | 30 | | | | +----+-------------------------------------------------------+----------------+ | | +Projection | 1 | $autoint_1 AS `1` | 30 | | | | +----+-------------------------------------------------------+----------------+ | | +AntiConditionalApply | 2 | | 30 | Fused in Pipeline 7 | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +Top | 3 | anon_1 ASC LIMIT 1 | 1 | In Pipeline 6 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +Projection | 4 | length(p) AS anon_1 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Filter | 5 | length(p) > $autoint_0 | 1 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Projection | 6 | (a)-[anon_0*]->(b) AS p | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +VarLengthExpand(Into) | 7 | (a)-[anon_0:R*]->(b) | 4 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 8 | a, b | 100 | Fused in Pipeline 5 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +Apply | 9 | | 100 | | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +Optional | 10 | a, b | 100 | In Pipeline 4 | | | | +----+-------------------------------------------------------+----------------+---------------------+ | | +ShortestPath | 11 | p = (a)-[anon_0:R*]->(b) WHERE length(p) > $autoint_0 | 30 | | | | | +----+-------------------------------------------------------+----------------+ | | | +Argument | 12 | a, b | 100 | Fused in Pipeline 3 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +CartesianProduct | 13 | | 100 | In Pipeline 2 | | |\ +----+-------------------------------------------------------+----------------+---------------------+ | | +NodeByLabelScan | 14 | b:B | 10 | In Pipeline 1 | | | +----+-------------------------------------------------------+----------------+---------------------+ | +NodeByLabelScan | 15 | a:A | 10 | In Pipeline 0 | +--------------------------+----+-------------------------------------------------------+----------------+---------------------+ ``` Better is to use the keyword-based SHORTEST. `MATCH p = SHORTEST 1 (a:A)-[:R]->{2,}(b:B) RETURN 1` --------- Co-authored-by: Jens Pryce-Åklundh <[email protected]>
1 parent 4a92c13 commit 7af0652

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

modules/ROOT/pages/patterns/reference.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,7 @@ They are similar to `SHORTEST 1` and `ALL SHORTEST`, but with several difference
13721372
* The path pattern is passed as an argument to the functions.
13731373
* The path pattern is limited to a single relationship pattern.
13741374
* To return results where the first and last node in the path are the same requires a change to the configuration setting link:{neo4j-docs-base-uri}/operations-manual/{page-version}/configuration/configuration-settings/#config_dbms.cypher.forbid_shortestpath_common_nodes[`dbms.cypher.forbid_shortestpath_common_nodes`].
1375+
* The minimum path length, also called the lower bound of the variable length relationship pattern, should be 0 or 1.
13751376

13761377
Both functions will continue to be available, but they are not xref:appendix/gql-conformance/index.adoc[GQL conformant].
13771378

@@ -1414,7 +1415,7 @@ shortestPath((:A)-->+(:B))
14141415
[[shortest-functions-rules-path-pattern-length]]
14151416
==== Path pattern length
14161417

1417-
There must be exactly one relationship pattern in the path pattern.
1418+
There must be exactly one relationship pattern in the path pattern, and the lower bound should be 0 or 1.
14181419

14191420
.Allowed
14201421
[source]
@@ -1427,6 +1428,8 @@ shortestPath((a)-[:R*1..5]-(b))
14271428
----
14281429
shortestPath((a)-[:R*1..5]-(b)-->(:X))
14291430
1431+
shortestPath((a)-[:R*2..5]-(b))
1432+
14301433
shortestPath((:A))
14311434
14321435
allShortestPaths((a:A)-[:S*]->(:B), (a)-[:R*1..3]->(:C))

0 commit comments

Comments
 (0)