Cypher Query Language
Traverse supports the Cypher query language for creating, reading, updating, and deleting graph data.
Clauses
| Clause | Description |
MATCH | Pattern-match nodes and relationships |
OPTIONAL MATCH | Left-outer-join pattern matching (unmatched rows produce nulls) |
CREATE | Create nodes and relationships |
MERGE | Match or create (upsert) with ON CREATE SET / ON MATCH SET |
DELETE / DETACH DELETE | Delete elements (detach removes connected edges first) |
SET | Set properties, add labels, or merge/replace properties |
REMOVE | Remove properties or labels |
WITH | Chain query parts, project intermediate results (supports DISTINCT, ORDER BY, SKIP, LIMIT, WHERE) |
RETURN | Define output columns (supports DISTINCT, ORDER BY, SKIP, LIMIT) |
WHERE | Filter results |
ORDER BY | Sort results (ASC / DESC) |
LIMIT | Limit number of results |
SKIP | Skip N results |
UNION / UNION ALL | Combine result sets (with or without deduplication) |
UNWIND | Expand a list into rows |
CALL | Call a procedure with YIELD |
FOREACH | Iterate and apply updates |
LOAD CSV | Import CSV data (LOAD CSV [WITH HEADERS] FROM url AS row [FIELDTERMINATOR char]) |
EXPLAIN | Show query plan without executing |
PROFILE | Execute and show plan with runtime stats |
Data Types
| Type | Description | Example |
NULL | Missing or undefined value | null |
BOOLEAN | True or false | true, false |
INTEGER | 64-bit signed integer | 42, -100 |
FLOAT | 64-bit floating point | 3.14, -2.5e-3 |
STRING | UTF-8 text | "hello", 'hello' |
LIST | Ordered collection | [1, 2, 3] |
MAP | Key-value pairs | {key: "val"} |
NODE | Graph vertex with labels and properties | — |
RELATIONSHIP | Graph edge with type and properties | — |
PATH | Alternating nodes and edges | — |
DATE | Calendar date | date("2026-01-15") |
LOCAL_TIME | Time without timezone | localtime("09:30:00") |
TIME | Time with timezone offset | time("09:30:00+02:00") |
LOCAL_DATE_TIME | Datetime without timezone | localdatetime("2026-01-15T09:30") |
DATE_TIME | Datetime with timezone | datetime() |
DURATION | Duration value | duration("P1Y2M3D") |
Patterns
Node Patterns
() -- anonymous node
(n) -- named node
(n:Person) -- with label
(n:Person {name: "Alice"}) -- with inline properties
(n:Person:Employee) -- multiple labels
Relationship Patterns
(a)-[r]->(b) -- directed (outgoing)
(a)<-[r]-(b) -- directed (incoming)
(a)-[r]-(b) -- undirected (either direction)
(a)-[r:KNOWS]->(b) -- typed
(a)-[r:KNOWS|LIKES]->(b) -- multiple types (OR)
(a)-[r:KNOWS {since: 2020}]->(b) -- with properties
(a)-[*1..3]->(b) -- variable-length (1 to 3 hops)
(a)-[*3]->(b) -- exactly 3 hops
(a)-[*2..]->(b) -- at least 2 hops
(a)-[*..5]->(b) -- up to 5 hops
Named Paths
p = (a)-[:KNOWS]->(b) -- bind entire path to variable
Operators
| Category | Operators |
| Comparison | =, <>, <, >, <=, >= |
| Boolean | AND, OR, XOR, NOT |
| String | STARTS WITH, ENDS WITH, CONTAINS, =~ (regex) |
| Null | IS NULL, IS NOT NULL |
| List | IN, list[index], list[start..end] |
| Math | +, -, *, /, %, ^ |
| String concat | + |
Functions
String Functions
| Function | Description |
toUpper(s) | Convert to uppercase |
toLower(s) | Convert to lowercase |
trim(s) | Remove leading/trailing whitespace |
ltrim(s), rtrim(s) | Trim left or right |
replace(s, from, to) | Replace occurrences |
substring(s, start [, len]) | Extract substring |
left(s, n), right(s, n) | First/last N characters |
split(s, delim) | Split into list |
reverse(s) | Reverse string |
Math Functions
| Function | Description |
abs(x) | Absolute value |
ceil(x) | Ceiling |
floor(x) | Floor |
round(x) | Round to nearest integer |
sign(x) | Sign (−1, 0, or 1) |
sqrt(x) | Square root |
log(x) | Natural logarithm |
log10(x) | Base-10 logarithm |
exp(x) | ex |
e() | Euler's number (2.71828...) |
pi() | Pi (3.14159...) |
rand() | Pseudo-random number in [0, 1) |
Aggregate Functions
| Function | Description |
count(expr) / count(*) | Count non-null values or rows (supports DISTINCT: count(DISTINCT x)) |
sum(expr) | Sum of numeric values |
avg(expr) | Average |
min(expr) | Minimum value |
max(expr) | Maximum value |
collect(expr) | Collect into list |
percentileDisc(expr, p) | Discrete percentile (nearest value) |
percentileCont(expr, p) | Continuous percentile (interpolated) |
stDev(expr) | Sample standard deviation |
stDevP(expr) | Population standard deviation |
List Functions
| Function | Description |
size(list) / length(list) | Number of elements |
head(list) | First element (or null) |
last(list) | Last element (or null) |
tail(list) | All but first element |
reverse(list) | Reverse the list |
range(start, end [, step]) | Generate integer range |
coalesce(expr1, expr2, ...) | First non-null argument |
Predicate Functions
| Function | Description |
exists(expr) | True if the value is not null |
all(x IN list WHERE pred) | True if predicate holds for all elements |
any(x IN list WHERE pred) | True if predicate holds for at least one element |
none(x IN list WHERE pred) | True if predicate holds for no elements |
single(x IN list WHERE pred) | True if predicate holds for exactly one element |
Type Conversion
| Function | Description |
toString(x) | Convert to string |
toInteger(x) / toInt(x) | Convert to integer |
toFloat(x) | Convert to float |
toBoolean(x) | Convert to boolean |
typeName(x) / valueType(x) | Runtime type name as string |
Graph Element Functions
| Function | Description |
id(n) | Internal element ID |
labels(n) | Node labels as list |
type(r) | Relationship type |
keys(n) | Property keys |
properties(n) | All properties as map |
startNode(r) | Start node of a relationship |
endNode(r) | End node of a relationship |
Path Functions
| Function | Description |
nodes(path) | List of nodes in a path |
relationships(path) / rels(path) | List of relationships in a path |
length(path) | Number of relationships in a path |
Temporal Functions
Constructors
| Function | Description |
date() / date(map) / date(string) | Create a date value |
localtime() | Create a local time value |
time() | Create a time with timezone offset |
localdatetime() | Create a local datetime |
datetime() | Create a datetime with timezone |
duration(string) | Create a duration (ISO-8601) |
Truncation
Truncate a temporal value to a coarser precision:
date.truncate(temporal)
localtime.truncate(temporal)
time.truncate(temporal)
localdatetime.truncate(temporal)
datetime.truncate(temporal)
Duration Computation
| Function | Description |
duration.between(t1, t2) | Duration between two temporal values |
duration.inMonths(d) | Total months component |
duration.inDays(d) | Total days component |
duration.inSeconds(d) | Total seconds as float |
Epoch Conversion
| Function | Description |
datetime.fromEpoch(seconds) | Datetime from Unix seconds |
datetime.fromEpochMillis(ms) | Datetime from Unix milliseconds |
timestamp() | Current Unix timestamp (milliseconds) |
Clock Functions
Each temporal type supports three clock sources:
datetime.transaction() -- fixed at transaction start
datetime.statement() -- fixed at statement start
datetime.realtime() -- current wall clock
Also available for date, localtime, time, localdatetime.
Schema Commands
Node Indexes
-- Create a named index
CREATE INDEX idx_person_name FOR (n:Person) ON (n.name);
-- Legacy syntax (also supported)
CREATE INDEX ON :Person(name);
-- Drop by name
DROP INDEX idx_person_name;
DROP INDEX idx_person_name IF EXISTS;
-- List all indexes
SHOW INDEXES;
Edge Indexes
-- Index on edge property
CREATE EDGE INDEX idx_knows_since ON :KNOWS(since);
-- Index on edge type only (speeds up type-filtered traversals)
CREATE EDGE INDEX idx_knows ON :KNOWS;
-- Drop
DROP EDGE INDEX idx_knows_since;
Constraints
-- Uniqueness constraint
CREATE CONSTRAINT unique_person_email FOR (n:Person) REQUIRE n.email IS UNIQUE;
-- Not-null constraint
CREATE CONSTRAINT person_name_required FOR (n:Person) REQUIRE n.name IS NOT NULL;
-- Drop
DROP CONSTRAINT unique_person_email;
DROP CONSTRAINT unique_person_email IF EXISTS;
-- List all constraints
SHOW CONSTRAINTS;
Analyze Graph
-- Collect statistics for query optimization
ANALYZE GRAPH;
-- Analyze specific labels
ANALYZE GRAPH LABEL Person, Company;
User Management
CREATE USER alice SET PASSWORD 'hunter2' SET ROLE EDITOR;
ALTER USER alice SET ROLE ADMIN;
DROP USER alice;
SHOW USERS;
Shortest Path
-- Single shortest path (BFS)
MATCH p = shortestPath((a:Person {name: "Alice"})-[*..15]->(b:Person {name: "Bob"}))
RETURN p;
-- All shortest paths
MATCH p = allShortestPaths((a)-[*..5]->(b))
RETURN p;
-- Weighted shortest path (Dijkstra)
MATCH p = (a:City {name: "Paris"})-[r *wShortest (r, node | r.distance) totalCost]->(b:City {name: "Berlin"})
RETURN p, totalCost;
Expressions
CASE
-- Searched CASE
MATCH (n:Person)
RETURN n.name,
CASE
WHEN n.age < 18 THEN "minor"
WHEN n.age < 65 THEN "adult"
ELSE "senior"
END AS category;
-- Simple CASE
RETURN CASE n.status WHEN "A" THEN "Active" WHEN "I" THEN "Inactive" ELSE "Unknown" END;
List Comprehension
-- Transform list with optional filter
RETURN [x IN range(1,10) WHERE x % 2 = 0 | x * x] AS squares;
-- From a path
MATCH p = (a)-[*1..3]->(b)
RETURN [node IN nodes(p) | node.name] AS names;
Pattern Comprehension
-- Collect values from matched sub-patterns
MATCH (p:Person)
RETURN p.name, [(p)-[:KNOWS]->(f) | f.name] AS friends;
Reduce
-- Fold/reduce over a list
RETURN reduce(total = 0, x IN [1,2,3,4,5] | total + x) AS sum;
Map Projection
-- Project specific properties from a node
MATCH (p:Person)
RETURN p {.name, .age} AS person;
Existential Subqueries
-- Check if a pattern exists
MATCH (p:Person)
WHERE EXISTS { (p)-[:KNOWS]->(:Person {name: "Alice"}) }
RETURN p.name;
Count Subqueries
-- Count matching sub-patterns
MATCH (p:Person)
WHERE COUNT { (p)-[:KNOWS]->() } > 5
RETURN p.name;
Parameters
Use $param syntax to pass query parameters safely:
MATCH (n:Person) WHERE n.name = $name RETURN n;
LOAD CSV
-- With headers (columns as map keys)
LOAD CSV WITH HEADERS FROM 'file:///path/to/data.csv' AS row
CREATE (n:Person {name: row.name, age: toInteger(row.age)});
-- Custom delimiter
LOAD CSV WITH HEADERS FROM 'file:///data.tsv' AS row FIELDTERMINATOR '\t'
CREATE (n:Record {id: row.id});
SET Variants
-- Set individual properties
SET n.name = "Alice", n.age = 30;
-- Replace all properties (removes existing ones)
SET n = {name: "Alice", age: 30};
-- Merge properties (keeps existing, adds/overwrites specified)
SET n += {age: 31, email: "alice@example.com"};
-- Add a label
SET n:Employee;
RETURN and WITH
-- Return all variables in scope
MATCH (n:Person)-[r]->(m)
RETURN *;
-- Pass all variables through WITH
MATCH (n:Person)
WITH * WHERE n.age > 25
RETURN n.name;
Procedures
-- Call a procedure and yield specific columns
CALL db.labels() YIELD label
RETURN label;
-- Yield all columns
CALL db.indexes() YIELD *;
Query Examples
Create Data
CREATE (a:Person {name: "Alice", age: 30})
CREATE (b:Person {name: "Bob", age: 25})
CREATE (a)-[:KNOWS {since: 2020}]->(b)
RETURN a, b;
Read & Filter
MATCH (p:Person)
WHERE p.age > 25
RETURN p.name, p.age
ORDER BY p.age DESC
LIMIT 10;
Regex Filtering
MATCH (p:Person)
WHERE p.name =~ 'Al.*'
RETURN p.name;
Aggregation
MATCH (p:Person)-[:KNOWS]->(friend)
RETURN p.name, count(friend) AS friendCount
ORDER BY friendCount DESC;
Variable-Length Paths
MATCH path = (a:Person {name: "Alice"})-[:KNOWS*1..3]->(b)
RETURN b.name, length(path) AS distance;
Merge (Upsert)
MERGE (p:Person {name: "Charlie"})
ON CREATE SET p.created = datetime()
ON MATCH SET p.lastSeen = datetime()
RETURN p;