Cypher Query Language

Traverse supports the Cypher query language for creating, reading, updating, and deleting graph data.

Clauses

ClauseDescription
MATCHPattern-match nodes and relationships
OPTIONAL MATCHLeft-outer-join pattern matching (unmatched rows produce nulls)
CREATECreate nodes and relationships
MERGEMatch or create (upsert) with ON CREATE SET / ON MATCH SET
DELETE / DETACH DELETEDelete elements (detach removes connected edges first)
SETSet properties, add labels, or merge/replace properties
REMOVERemove properties or labels
WITHChain query parts, project intermediate results (supports DISTINCT, ORDER BY, SKIP, LIMIT, WHERE)
RETURNDefine output columns (supports DISTINCT, ORDER BY, SKIP, LIMIT)
WHEREFilter results
ORDER BYSort results (ASC / DESC)
LIMITLimit number of results
SKIPSkip N results
UNION / UNION ALLCombine result sets (with or without deduplication)
UNWINDExpand a list into rows
CALLCall a procedure with YIELD
FOREACHIterate and apply updates
LOAD CSVImport CSV data (LOAD CSV [WITH HEADERS] FROM url AS row [FIELDTERMINATOR char])
EXPLAINShow query plan without executing
PROFILEExecute and show plan with runtime stats

Data Types

TypeDescriptionExample
NULLMissing or undefined valuenull
BOOLEANTrue or falsetrue, false
INTEGER64-bit signed integer42, -100
FLOAT64-bit floating point3.14, -2.5e-3
STRINGUTF-8 text"hello", 'hello'
LISTOrdered collection[1, 2, 3]
MAPKey-value pairs{key: "val"}
NODEGraph vertex with labels and properties
RELATIONSHIPGraph edge with type and properties
PATHAlternating nodes and edges
DATECalendar datedate("2026-01-15")
LOCAL_TIMETime without timezonelocaltime("09:30:00")
TIMETime with timezone offsettime("09:30:00+02:00")
LOCAL_DATE_TIMEDatetime without timezonelocaldatetime("2026-01-15T09:30")
DATE_TIMEDatetime with timezonedatetime()
DURATIONDuration valueduration("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

CategoryOperators
Comparison=, <>, <, >, <=, >=
BooleanAND, OR, XOR, NOT
StringSTARTS WITH, ENDS WITH, CONTAINS, =~ (regex)
NullIS NULL, IS NOT NULL
ListIN, list[index], list[start..end]
Math+, -, *, /, %, ^
String concat+

Functions

String Functions

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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;