Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document lower bound restriction for shortestPath() and allShortestPath() functions #1146

Conversation

WilcoNeo
Copy link
Contributor

@WilcoNeo WilcoNeo commented Jan 8, 2025

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

@WilcoNeo WilcoNeo force-pushed the dev-document-shortestPath-function-lowerBound-restriction branch from 5295434 to d25c1ba Compare January 8, 2025 09:46
@blouerat blouerat self-assigned this Jan 9, 2025
@dogofbrian
Copy link
Contributor

As this is a rule, it should get a mention in the Rules section. It could be kept to a minimum e.g.

Path pattern length
There must be exactly on relationship pattern in the path pattern, and the lower bound should be 0 or 1.

Then add another example under Not allowed e.g.shortestPath((a)-[:R*2..10]-(b))

@WilcoNeo WilcoNeo force-pushed the dev-document-shortestPath-function-lowerBound-restriction branch from 946efca to 148ec59 Compare January 10, 2025 08:39
@neo-technology-commit-status-publisher
Copy link
Collaborator

Thanks for the documentation updates.

The preview documentation has now been torn down - reopening this PR will republish it.

@JPryce-Aklundh JPryce-Aklundh added cherry-pick-this-to-5.x Cherry pick this PR changes to the 5.x branch cherry-pick-this-to-cypher-25 labels Jan 10, 2025
@JPryce-Aklundh JPryce-Aklundh merged commit 57ae186 into neo4j:dev Jan 10, 2025
5 checks passed
JPryce-Aklundh added a commit that referenced this pull request Jan 10, 2025
…th() 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]>
JPryce-Aklundh added a commit that referenced this pull request Jan 10, 2025
…th() 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants