Docs
View as markdown

Cypher overview

The Cypher dialect relate runs, from the openCypher floor to Neo4j's Cypher 25 and GQL-aligned extensions, the preview features, and what is out of scope.

cyphercli

relate runs openCypher The open specification of Cypher and its Technology Compatibility Kit (TCK) of scenarios; relate treats it as the floor of its dialect. Read more in the glossary, plus a large part of Neo4j's Cypher 25 and its extensions aligned with GQL, the ISO graph query language. Statements run as Cypher 25 unless a CYPHER 5 prefix says otherwise. Preview features stay off until RELATE_PREVIEW names them. Cypher for servers and clusters, such as users, roles and composite databases, is out of scope for an engine that runs inside one process.

Synopsis

[CYPHER 5 | CYPHER 25] [EXPLAIN | PROFILE] <statement>
SettingDefaultValues
Language versionCYPHER 25 for every namespace, as SHOW DATABASES reports in defaultLanguageA CYPHER 5 or CYPHER 25 prefix on one statement. ALTER DATABASE <name> SET DEFAULT LANGUAGE CYPHER 5 changes only what SHOW DATABASES reports (Cypher versions)
Preview featuresNone enabledRELATE_PREVIEW=<feature>[,<feature>…] in the environment of the process that opens the store
Plan prefixesNoneEXPLAIN plans without running; PROFILE runs and measures (tune a query)

Conformance

The openCypher Technology Compatibility Kit (TCK) is the language contract. The relate project measures coverage against it outside the engine's own repository, and its published compliance record says that "no engine document publishes a current TCK pass count any more". This page therefore states no current pass rate.

MeasureWhat it coversPublished result
Spec harnessNeo4j's Cypher spec suites, the openCypher TCK among them, run against the engine built from each ready-for-review pull requestCoverage reported on every such pull request; reporting only, never a merge gate; no pass count published
In-repo TCK run, retired 2026-11-05A pinned openCypher TCK 2024.3 corpus, checked strictly: error class, error phase, and side effects3,892 of 3,892 expanded scenarios passed with 0 skipped, in CI, until 2026-11-05. The pinned corpus was not unmodified 2024.3: one scenario was removed and seven were re-pinned to current Neo4j behavior. The claim is retired
Cypher Improvement Proposal (CIP) suiteNeo4j Cypher beyond the TCK, derived from Neo4j's CIP documentsLanding run in the spec harness: 4,942 passed, 924 failing and 51 skipped of 5,917 scenarios. A tracker, not a floor

Supported Cypher 25 and GQL-aligned features

Each feature runs on the WebAssembly build the cells on this site use and on the CLI, without an opt-in. The exception is a generated identifier: uuid() with no argument and randomUUID() run on the CLI and the clients, and on the WebAssembly build the engine panics with time not implemented on this platform and the instance stops. uuid('<uuid string>') runs on both.

FeatureForm
Label expressions(n:Person|Project), (n:Person&!Bot), (n:%), (n IS Person)
Pattern predicates(p:Person WHERE p.role = 'engineer')
Quantified path patterns((a)-[:KNOWS]->(b)){1,3}, -[:KNOWS]->{1,3}
Path selectors and modesSHORTEST 1, ANY SHORTEST, ALL SHORTEST, TRAIL, ACYCLIC, WALK
Dynamic labels and typesMATCH (n:$($label)), CREATE ()-[:$($type)]->()
Type predicatesx IS :: INTEGER, valueType(x)
New clausesLET, FILTER, NEXT, WHEN … THEN … ELSE, FINISH, INSERT
Subquery expressionsCOUNT { … }, COLLECT { … }, EXISTS { … }
CALL scope clauseCALL (p) { … }, CALL () { … }
Batched writesCALL (row) { … } IN TRANSACTIONS OF <n> ROWS
String interpolations'{p.name} works on {proj.name}'
Explicit groupingRETURN p.role AS role, count(*) AS n GROUP BY role
Concatenation'rel' || 'ate', [1] || [2]
Map comprehensions{i IN [1, 2] | toString(i): i * 10}
Value typesVECTOR through vector(…), UUID through uuid('<uuid string>')
Graph typesCREATE GRAPH TYPE, ALTER CURRENT GRAPH TYPE, SHOW CURRENT GRAPH TYPE
Index searchSEARCH over vector and full-text indexes (search)
Unicode identifiersRETURN 1 AS café, unquoted

Preview features

A preview feature A Cypher feature from a not-yet-settled proposal that relate ships switched off; it runs only when RELATE_PREVIEW names it when the store opens. Read more in the glossary ships in the engine and stays off until its name is in RELATE_PREVIEW, which is read once when the store A relate database: a directory, a single .rl file, or :memory:, opened with --database. Read more in the glossary opens. Several names are separated by commas. An unknown name fails the open with exit code 1 and lists the known names. The error a feature gives while it is off depends on the feature, as the When off column shows. Most give the preview message, semantic error: SemanticError: preview feature '<name>' is not enabled: set RELATE_PREVIEW=<name>, which names the opt-in. A name gate fails as an unknown function, and a few fail as the parser or the SEARCH rules would without the feature; those messages do not mention RELATE_PREVIEW.

NameEnablesWhen off
hybrid-searchCOMBINE inside SEARCH: weighted reciprocal-rank fusion of two or more index searchesThe preview message
local-callablesDEFINE FUNCTION and DEFINE PROCEDURE, scoped to one statementThe preview message
ontologyThe db.ontology.* procedures: get, set, apply and dropThe preview message; any other db.ontology.* name is syntax error: ProcedureNotFound: <name> with the feature on or off
graph-type-opt-propsOptional properties, prop :: ANY, in a graph typeThe preview message
graph-type-default-valuesDEFAULT ON COMMIT <value> on a graph type's propertyThe preview message
graph-type-implied-labelsImplied labels and inheritance between graph typesThe preview message
obfuscated-literalsThe ****** placeholder literalsyntax error: parse error: unexpected token "*"
mixed-label-syntaxMixing :A:B, GQL label symbols and IS across one clause's label expressionssyntax error: parse error: InvalidLabelExpression: mixing label expression symbols (|, &, !, and %) with colon (:) between labels is not allowed, or for IS, syntax error: parse error: MixedIsAndColonConjunction: cannot mix the IS introducer with colon-conjunction within the same clause
float16-coordinate-typesFLOAT16 and BFLOAT16 vector coordinatesThe preview message
chronological-comparisonsIS [NOT] BEFORE, AFTER, SAME INSTANT and SAME REPRESENTATIONThe preview message
complex-search-patternsSEARCH on a MATCH with more than one node or hopThe MATCH shape errors in the search rules: SearchClauseTooComplexPattern or SearchClauseMultipleBoundVariables
coll-zipThe coll.zip function (name gate)syntax error: UnknownFunction: unknown function coll.zip()
coll-hasThe coll.hasAnyOf, coll.hasAllOf and coll.hasNoneOf functions (name gate)syntax error: UnknownFunction: unknown function <name>()
gql-stddev-aliasesThe stddev_samp and stddev_pop spellings (name gate)syntax error: UnknownFunction: unknown function <name>()

Out of scope

ArearelateAlternative
Users, roles, and privilegesNot implementedFile permissions on the store, --read-only, and relate serve --auth on a served store
Several databasesThree fixed namespaces per store: neo4j for data, system, and system_ontologies (listed, not queryable)One store per graph
Database administrationOnly SHOW DATABASE[S], SHOW DEFAULT DATABASE, SHOW HOME DATABASE and ALTER DATABASE … SET DEFAULT LANGUAGE; anything else fails with semantic error: UnsupportedAdministrationCommand: Unsupported administration command: <statement>—
Composite, remote and sharded databases; clusteringNot implemented—
Queries across graphsA statement runs against one graphQuery each store and join the results in your code
APOC and Graph Data Science librariesNot includedThe built-in functions and procedures; differences from Neo4j lists the replacements
Long explicit path boundsAn explicit bound of more than 500 hops fails with TraversalDepthExceeded--max-traversal-depth <n>, up to 2000

Limitations lists each limit and the reason for it.

Examples

The cells run in page order on one in-memory store, starting from the shared example graph:

Cypher
CREATE (ada:Person {name: 'Ada', role: 'engineer'}),
       (grace:Person {name: 'Grace', role: 'engineer'}),
       (noor:Person {name: 'Noor', role: 'maintainer'}),
       (relate:Project {name: 'relate', language: 'Rust'}),
       (tck:Project {name: 'opencypher-tck', language: 'Gherkin'}),
       (ada)-[:WORKS_ON {since: 2024}]->(relate),
       (grace)-[:WORKS_ON {since: 2023}]->(relate),
       (grace)-[:WORKS_ON {since: 2022}]->(tck),
       (noor)-[:MAINTAINS]->(relate),
       (ada)-[:KNOWS]->(grace)
Recorded result
(no rows) · nodes created: 5, relationships created: 5, properties set: 13, labels added: 5

The default language of each namespace:

Cypher
SHOW DATABASES YIELD name, defaultLanguage RETURN name, defaultLanguage
Recorded result
namedefaultLanguage
"neo4j""CYPHER 25"
"system""CYPHER 25"
"system_ontologies""CYPHER 25"

3 rows

A label expression A test on a node's labels or a relationship's type built with &, |, ! and %, such as (n:Person|Project) or (n IS Person). Read more in the glossary with a pattern predicate, and a quantified path pattern:

Cypher
MATCH (p:Person&!Project WHERE p.role = 'engineer') RETURN p.name AS name ORDER BY name
Recorded result
name
"Ada"
"Grace"

2 rows

Cypher
MATCH (:Person {name: 'Ada'}) ((a)-[:KNOWS|WORKS_ON]->(b)){1,2} (reached)
RETURN DISTINCT reached.name AS reached ORDER BY reached
Recorded result
reached
"Grace"
"opencypher-tck"
"relate"

3 rows

LET, FILTER and a COUNT subquery in one pipeline:

Cypher
MATCH (p:Person)
LET projects = COUNT { (p)-[:WORKS_ON]->() }
FILTER projects > 0
RETURN p.name AS name, projects ORDER BY name
Recorded result
nameprojects
"Ada"1
"Grace"2

2 rows

String interpolation, and explicit grouping:

Cypher
MATCH (p:Person)-[w:WORKS_ON]->(proj:Project)
RETURN s'{p.name} works on {proj.name}' AS line ORDER BY line
Recorded result
line
"Ada works on relate"
"Grace works on opencypher-tck"
"Grace works on relate"

3 rows

Cypher
MATCH (p:Person) RETURN p.role AS role, count(*) AS people GROUP BY role ORDER BY role
Recorded result
rolepeople
"engineer"2
"maintainer"1

2 rows

A preview feature without its opt-in:

Cypher
DEFINE FUNCTION twice(x) = x * 2
RETURN twice(21) AS answer
Expected error
error: semantic error: SemanticError: preview feature 'local-callables' is not enabled: set RELATE_PREVIEW=local-callables

The same statement on the CLI, with the opt-in in the command's environment:

RELATE_PREVIEW=local-callables relate --mode envelope "DEFINE FUNCTION twice(x) = x * 2 RETURN twice(21) AS answer"
{"columnTypes":["INTEGER"],"columns":["answer"],"notifications":[],"planCache":"miss","rows":[{"answer":42}],"timings":{"elapsed_ms":0.438125,"execute_ms":0.246333,"lex_parse_ms":0.025042,"lower_ms":0.042208,"parse_ms":0.113125,"plan_ms":0.07037500000000001,"result_generation_ms":0.00020800000000000001,"rewrite_ms":0.020583},"truncated":false}

See also