Matching and filtering graphs
On this page
MATCH
Find subgraphs matching one or more patterns.
MATCH (p:Person) RETURN p.name;
MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a.name, b.name, r.since;
// inline property predicate (equality on each given key)
MATCH (p:Person {name: 'Ada', age: 36}) RETURN p;
Multi-pattern MATCH — comma-separated patterns are joined (a Cartesian
product over patterns that don't share a variable; a join over those that do):
MATCH (a:Person), (c:Company) RETURN a.name, c.name; // cross product
MATCH (a:Person)-[:WORKS_AT]->(c), (c)-[:IN]->(city) // shared c => join
RETURN a.name, city.name;
Inline pattern predicates — node and relationship patterns take an inline
WHERE (Cypher 5's pattern predicate):
MATCH (p:Person WHERE p.age > 30)-[r:KNOWS WHERE r.since < 2020]->(f)
RETURN p.name, f.name;
The predicate is evaluated once the whole pattern is bound, so it may reference
any pattern variable ([r:T WHERE r.w > b.min] beside an end node b works) —
identical cost to the same predicate in a clause WHERE. It is not allowed on a
variable-length relationship ([r:T* WHERE …] is an error).
The planner picks how to source the anchor node (index seek, label-token scan, or
full scan), considering both ends of each pattern and starting from the
cheaper one — writing (a:Entity)-[:R]->(b:Indexed {k: v}) seeks on b and
expands back to a; see EXPLAIN below.
OPTIONAL MATCH
Like MATCH, but if the pattern matches nothing for an input row, the row is
kept with the pattern's new variables bound to null (a left-outer join).
MATCH (p:Person)
OPTIONAL MATCH (p)-[:KNOWS]->(f)
RETURN p.name, f.name; // f.name is null for people who know nobody
WHERE
Filters the current rows. Attaches to MATCH, OPTIONAL MATCH and WITH.
Uses three-valued logic — only rows where the predicate is true survive
(false and null are dropped). See Operators and expressions.
MATCH (p:Person)
WHERE p.age >= 30 AND p.age < 50 AND p.name STARTS WITH 'A'
RETURN p.name;
MATCH (p:Person) WHERE p.nick IS NULL RETURN p.name;
MATCH (p:Person) WHERE p.name IN ['Ada', 'Bob', 'Cy'] RETURN p;
// pattern existence as a predicate:
MATCH (p:Person) WHERE EXISTS { (p)-[:KNOWS]->() } RETURN p.name;
Related articles
Indexes and constraints · Procedure directory · Transactions and concurrency