Cypher fundamentals
|
This section documents the current Neo4j This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, as Neo4j iterates quickly. This section’s bibliography lists the reference material consulted while preparing these pages. |
Cypher is Neo4j’s declarative query language: instead of joins over tables, a query describes a graph pattern to match or create, using nodes in round brackets and relationships in square brackets. This page covers that pattern syntax, the handful of clauses every query is built from, and query parameters.
The pattern: ()-[]-()
A pattern is an ASCII-art sketch of a path through the graph. () is a node, [] is a relationship, and a
dash on either side of the relationship joins them; an arrow head (→ or ←) fixes the direction, while
a plain dash on both sides matches a relationship in either direction.
// a node with a variable, a label, and a property map
(a:Person {name: "Keanu Reeves"})
// a directed relationship with a type and a property map
(a:Person)-[:ACTED_IN {roles: ["Neo"]}]->(m:Movie)
// an undirected pattern -- matches the relationship in either direction
(a:Person)-[:KNOWS]-(b:Person)
Every element in a pattern is optional except the brackets themselves: () alone matches any node, [r]
alone binds a relationship variable without constraining its type, and a node or relationship can carry a
label/type with no property map, or a property map with no variable name.
|
This page has to write Cypher property maps — |
Core clauses
The read/write clauses below cover most day-to-day Cypher. CREATE and MERGE write patterns; MATCH and
WHERE read and filter them; RETURN shapes the output; SET/REMOVE mutate properties and labels;
DELETE/DETACH DELETE remove data.
// CREATE: always adds new nodes/relationships, even if an identical one exists
CREATE (m:Movie {title: "The Matrix", released: 1999})
CREATE (a:Person {name: "Keanu Reeves"})-[:ACTED_IN {roles: ["Neo"]}]->(m)
// MATCH + WHERE: find existing patterns and filter them
MATCH (a:Person)-[r:ACTED_IN]->(m:Movie)
WHERE m.released >= 1990 AND a.name STARTS WITH "Keanu"
RETURN a.name, r.roles, m.title
ORDER BY m.released
MERGE is Cypher’s idempotent write: it matches the given pattern and only creates it when no match exists,
which makes it the standard way to load data without producing duplicates on a re-run.
// MERGE: match-or-create, keyed on the properties given
MERGE (m:Movie {title: "The Matrix"})
ON CREATE SET m.released = 1999, m.createdAt = datetime()
ON MATCH SET m.lastSeenAt = datetime()
MERGE (a:Person {name: "Keanu Reeves"})
MERGE (a)-[r:ACTED_IN]->(m)
ON CREATE SET r.roles = ["Neo"]
SET writes properties or adds labels; REMOVE is its inverse for labels and properties. DELETE removes
nodes or relationships that were matched, but a node with any relationship still attached refuses a plain
DELETE — DETACH DELETE removes the node’s relationships first, in the same statement.
// SET / REMOVE: mutate properties and labels
MATCH (m:Movie {title: "The Matrix"})
SET m.tagline = "Welcome to the Real World", m:Classic
REMOVE m.tagline, m:Classic
// DELETE fails here if `a` still has relationships attached
MATCH (a:Person {name: "Old Extra"})
DELETE a
// DETACH DELETE removes the node's relationships first, then the node
MATCH (a:Person {name: "Old Extra"})
DETACH DELETE a
Query parameters
Hardcoding literals into Cypher text defeats query-plan caching and invites injection when values come from
user input. Parameters — written $name in the query and supplied separately by the driver or the Cypher
shell — keep the query text stable across calls with different values, exactly the role bind variables play
in parameterized SQL.
// the query text never changes between calls; only the parameter values do
MATCH (a:Person {name: $name})-[:ACTED_IN]->(m:Movie)
WHERE m.released >= $sinceYear
RETURN m.title
// cypher-shell: set parameters before running a query that references them
:param name => "Keanu Reeves"
:param sinceYear => 1995
A property map such as \{name: $name\} combines both ideas: the map supplies the property to match or set,
and $name supplies its value as a parameter rather than a literal baked into the query text.
Coming from SQL
Readers arriving from a relational background can map most of the clauses above onto familiar operations:
MATCH plus WHERE plays the role of a SELECT with a WHERE and implicit joins along the pattern’s
relationships, CREATE/MERGE play INSERT/UPSERT, and SET/DELETE play UPDATE/DELETE. The
SQL Reference is the relational baseline this comparison is drawn against — the biggest conceptual shift is that a Cypher pattern makes relationships explicit, first-class parts of the
query text instead of implicit join conditions resolved through foreign keys.
Continue with the official reference for how Cypher fits into Neo4j overall (Cypher & Neo4j), the shape of a full query (Queries), and the complete clause list (Clauses).