Cypher fundamentals

This section documents the current Neo4j 2026.x calendar-versioned line — Neo4j moved from semantic to calendar versioning (YYYY.MM) in 2025, and the same line applies to the Graph Data Science library — as published at the Neo4j documentation, which is the reference these pages are written and verified against. No specific monthly patch is pinned. Some areas (Aura’s internal infrastructure, the Raft consensus implementation details, and the GDS Pregel API’s low-level internals) are linked, not documented in depth.

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.

An annotated Cypher pattern (a:Person \{name: $name\})-[:ACTED_IN \{roles: $roles\}]→(m:Movie)
// 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 — \{name: $name\} — in running prose, and that is exactly where a documentation gotcha shows up. AsciiDoc treats a literal \{ or \} in body text as the start of an attribute reference, so a curly brace typed unescaped in prose either vanishes or renders as broken text. Every brace mentioned inline in a sentence on this page is therefore escaped as \{ / \}, as it was in the paragraph above. Inside a [source,cypher] block, however, braces are shown unescaped, exactly as Cypher itself expects them — a source block is a literal block, not prose, so no escaping is needed or wanted there. Mixing the two up is the single most common formatting mistake when documenting Cypher.

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).