Path pattern expressions

Similar to existential subqueries, path pattern expressions can be used to assert whether a specified path exists at least once in a graph. While existential subqueries are more powerful and capable of performing anything achievable with path pattern expressions, path pattern expressions are more concise.

For more information about graph pattern matching in Cypher®, see Patterns.

Rules

Path pattern expressions have the following restrictions (use cases that require extended functionality should consider using existential subqueries instead):

  • Path pattern expressions may only use a subset of graph pattern semantics.

  • A path pattern expression must be a path pattern of length greater than zero. In other words, it must contain at least one relationship or variable-length relationship.

  • Path pattern expressions may not declare new variables. They can only reference existing variables.

  • Path pattern expressions may only be used in positions where a boolean expression is expected. The following sections will demonstrate how to use path pattern expressions in a WHERE clause.

Example graph

The following graph is used for the examples below:

path pattern expressions

To recreate the graph, run the following query in an empty Neo4j database:

CREATE (alice:Person {name:'Alice', age: 65, role: 'Project manager'}),
       (cecil:Person {name: 'Cecil', age: 25, role: 'Software developer'}),
       (cecilia:Person {name: 'Cecilia', age: 31, role: 'Software developer'}),
       (cecil)-[:WORKS_FOR {since: 2023}]->(alice),
       (cecilia)-[:WORKS_FOR {since: 2015}]->(alice)

Examples

Simple path pattern expression
MATCH (employee:Person)
WHERE (employee)-[:WORKS_FOR]->(:Person {name: 'Alice'})
RETURN employee.name AS employee
Result
employee

"Cecil"

"Cecilia"

Rows: 2

Path pattern expression including boolean operators NOT and AND
MATCH (employee:Person)
WHERE NOT employee.name = 'Cecil' AND (employee)-[:WORKS_FOR]->(:Person {name: 'Alice'})
RETURN employee.name AS employee
Result
employee

"Cecilia"

Rows: 1

For more information about Cypher’s boolean operators, see Predicate expressions → Boolean operators.

Patterns can be placed inside expressions.

Pattern inside an expression
RETURN NOT (:Person {name: "Alice"})<-[:WORKS_FOR {since: 2023}]-(:Person) AS patternCheck
Result
patternCheck

FALSE

Rows: 1

NOT is required in the above example to make the query a valid predicate expression. Without it, the query would be invalid because the expression would not return a BOOLEAN value.

The exists() function can be used to check for the presence of a pattern. Note that this function not as versatile as the EXISTS subqueries.

Using the exists() function to check if a pattern exists
RETURN exists((:Person)-[:WORKS_FOR {since: 2023}]->(:Person {name: "Alice"})) AS patternCheck
Result
patternCheck

TRUE

Rows: 1