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

Optimisation? Semantics? Consecutive (predicate-free) varLength pattern elements. #12081

Closed
Izhaki opened this issue Nov 16, 2018 · 2 comments
Closed

Comments

@Izhaki
Copy link

Izhaki commented Nov 16, 2018

Environment

  • Neo4j version: 3.4.9

Background

  • Doubt anyone will write a query like this in practice.
  • Very specific edge case:
    • Consecutive varLength relationships, with the same predicates (props, type - even if none).
    • The node between them involves no predicate (props, labels)

Description

Consider:

MATCH p = (:Person)-[*]-()-[*]-(:Movie)
RETURN p

The plan will include two VarLengthExpand(All) operators:

+-----------------------+
| Operator              |
+-----------------------+
| +ProduceResults       |
| |                     +
| +Projection           |
| |                     +
| +Filter               |
| |                     +
| +VarLengthExpand(All) |
| |                     +
| +VarLengthExpand(All) |
| |                     +
| +NodeByLabelScan      |
+-----------------------+

Which is rather bonkers.

Also note the result:

CREATE (a:Src),(b),(c),(d:Dst),(a)-[:R1 {x:'r1'}]->(b)-[:R2 {x:'r2'}]->(c)-[:R3 {x:'r3'}]->(d)

MATCH p = (:Src)-[*]-()-[*]-(:Dst)
RETURN relationships(p)

╒══════════════════════════════════╕
│"relationships(p)"                │
╞══════════════════════════════════╡
│[{"x":"r1"},{"x":"r2"},{"x":"r3"}]│
├──────────────────────────────────┤
│[{"x":"r1"},{"x":"r2"},{"x":"r3"}]│
└──────────────────────────────────┘

This is correct, but why would anyone like to do this?

This query can be rewritten as:

MATCH p = (:Person)-[*2..]-(:Movie)
RETURN p

Which is more efficient, and it only produces distinct paths:

MATCH p = (:Src)-[*2..]-(:Dst)
RETURN relationships(p)

╒══════════════════════════════════╕
│"relationships(p)"                │
╞══════════════════════════════════╡
│[{"x":"r1"},{"x":"r2"},{"x":"r3"}]│
└──────────────────────────────────┘

I'm sure you'll also be able to work out the arithmetic for queries like this:

MATCH p = (:Person)-[*2..5]-()-[*2..5]-(:Movie)
RETURN p

Anyhow, given the results are different, perhaps this is more of a case of semantics rather than optimisation.

@Izhaki Izhaki changed the title Optimisation: Rewrite (predicate-free) consecutive varLength pattern elements. Optimisation? Semantics? Consecutive (predicate-free) varLength pattern elements. Nov 19, 2018
@Hunterness
Copy link
Contributor

Good idea, thanks for the input. We will consider it for future development.

@Hunterness Hunterness self-assigned this Dec 10, 2018
@fickludd
Copy link
Contributor

Hi @Izhaki

Thank you for this interesting corner case. As this is such a narrow use case I feel that our performance efforts are better spent on other things, also given that it is easy to hand optimize a query from one form to the other if it is a bottleneck for some use case.

If you are interested in the subtle nuances of patterns, I encourage you to participate in the ongoing OpenCypher work around path patterns opencypher/openCypher#187, which is essentially about extending Cypher patterns with regex-like functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants