Pattern matching is the core of Cypher; nearly every query starts with MATCH.
MATCH finds all places in the graph where a pattern fits, binding variables for each match. RETURN says what to output.
MATCH (p:Person)-[:FOLLOWS]->(other:Person)
WHERE p.born < 1995
RETURN p.name, other.name
ORDER BY p.name
LIMIT 10Things to know:
- Properties in the pattern,
(p:Person {name: 'Ann'}), are shorthand for equality conditions inWHERE. WHEREsupports comparisons,AND/OR/NOT,IN [...],STARTS WITH,CONTAINS,=~regex andIS NULL. Missing properties arenull.- Leaving out the arrowhead,
-[:FOLLOWS]-, matches either direction. RETURNcan output nodes, relationships, properties, expressions and maps;ASrenames columns andDISTINCTremoves duplicates.ORDER BY,SKIPandLIMITwork like in SQL.
If a pattern matches nothing, the query returns no rows. Each MATCH row is one way the pattern fits, so a person following three people appears in three rows.
Always include labels in patterns: MATCH (n {name: 'Ann'}) without a label has to check every node in the database.
Example
// who does each person follow, oldest followers first
MATCH (p:Person)-[f:FOLLOWS]->(other:Person)
WHERE f.since >= 2021
RETURN p.name AS follower, other.name AS follows, f.since AS since
ORDER BY p.born, since;
// follower | follows | since
// "Ann" | "Bob" | 2021
// "Ann" | "Cy" | 2024
// "Cy" | "Bob" | 2023
// either direction: everyone connected to Bob by FOLLOWS
MATCH (:Person {name: 'Bob'})-[:FOLLOWS]-(x:Person)
RETURN collect(x.name) AS connected; // ["Ann", "Cy"] (order may vary)Remember
- MATCH binds variables for every place a pattern fits
- WHERE filters; inline
{k: v}is shorthand for equality - Omit the arrowhead to match both directions
- Always use labels so the planner can avoid scanning all nodes
Watch out for
- Omitting labels in MATCH, forcing a scan of every node.