Skip to content

Cypher Reference

CongraphDB implements a subset of the Cypher graph query language.

Clauses

MATCH

Find patterns in the graph.

MATCH (u:User)
MATCH (u:User)-[:KNOWS]->(f:User)
MATCH (u:User {name: 'Alice'})-[:KNOWS]->(f:User)

RETURN

Specify what to return from the query.

RETURN u.name, u.age
RETURN u.name AS username, COUNT(*) AS count
RETURN DISTINCT u.city

ORDER BY

Sort results with ASC/DESC modifiers on multiple columns.

-- Single column sort
MATCH (u:User)
RETURN u.name, u.age
ORDER BY u.age DESC

-- Multiple column sort
MATCH (p:Post)
RETURN p.title, p.created
ORDER BY p.created DESC, p.title ASC

-- Sort with aggregation
MATCH (u:User)-[:KNOWS]->(f:User)
RETURN u.name, COUNT(f) AS friend_count
ORDER BY friend_count DESC

SKIP / LIMIT

Offset and restrict result sets for pagination.

-- Basic pagination
MATCH (u:User)
RETURN u.name, u.age
ORDER BY u.name
SKIP 10 LIMIT 20

-- Get top 10 results
MATCH (u:User)
RETURN u.name, u.score
ORDER BY u.score DESC
LIMIT 10

-- Skip first 5, get next 10
MATCH (p:Post)
RETURN p.title
ORDER BY p.created DESC
SKIP 5 LIMIT 10

UNION

Combine results from multiple MATCH patterns.

-- Union of two patterns
MATCH (u:User)-[:FOLLOWS]->(f:User)
RETURN u.name AS name, f.name AS value
UNION
MATCH (u:User)-[:KNOWS]->(k:User)
RETURN u.name AS name, k.name AS value

-- Union with different node types
MATCH (u:User)
RETURN u.name AS name, u.email AS contact
UNION
MATCH (o:Organization)
RETURN o.name AS name, o.website AS contact

WHERE

Filter results.

WHERE u.age > 25
WHERE u.name = 'Alice' OR u.name = 'Bob'
WHERE u.name STARTS WITH 'A'
WHERE u.name IN ['Alice', 'Bob', 'Charlie']

CREATE

Create new nodes and relationships.

CREATE (u:User {name: 'Alice', age: 30})
CREATE (u:User)-[:KNOWS {since: 2020}]->(f:User)

DELETE

Remove nodes and relationships.

DELETE r
DELETE u
DETACH DELETE u

SET

Update properties.

SET u.age = 31
SET u:Active

REMOVE

Remove properties and labels from nodes and relationships.

-- Remove properties
MATCH (u:User {name: 'Alice'})
REMOVE u.age

-- Remove labels
MATCH (u:User {name: 'Alice'})
REMOVE u:Active

MERGE

Match existing nodes or create new ones if they don't exist. Supports conditional updates with ON MATCH and ON CREATE.

-- Basic MERGE
MERGE (u:User {name: 'Alice'})

-- MERGE with conditional updates
MERGE (u:User {name: 'Alice'})
ON CREATE SET u.created = timestamp(), u.age = 30
ON MATCH SET u.lastSeen = timestamp(), u.visitCount = coalesce(u.visitCount, 0) + 1
RETURN u

Operators

Comparison

Operator Description
= Equal
<> or != Not equal
< Less than
> Greater than
<= Less than or equal
>= Greater than or equal

Logical

Operator Description
AND Logical and
OR Logical or
NOT Logical not
XOR Exclusive or

String

Operator Description
STARTS WITH String starts with prefix
ENDS WITH String ends with suffix
CONTAINS String contains substring
=~ Regular expression match

Arithmetic

Operator Description
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulo
^ Exponentiation

Vector

Operator Description
<-> Cosine distance (recommended for embeddings)
<=> Euclidean distance (L2)
<= Negative inner product

Functions

Temporal

Function Description
date(string) Parse or create a date value
datetime() Get current datetime
datetime(string) Parse datetime string
timestamp() Unix timestamp in milliseconds
duration(string) Parse ISO 8601 duration
duration.between(start, end) Calculate duration between two dates

Temporal examples:

-- Create dates
RETURN date('2024-03-15') AS today

-- Current datetime
RETURN datetime() AS now

-- Timestamp
RETURN timestamp() AS epoch_ms

-- Duration calculation
MATCH (u:User {name: 'Alice'})-[:KNOWS {since: date('2020-01-01')}]->(f:User)
RETURN duration.between(date('2020-01-01'), date()).years AS years_known

Node and Label

Function Description
labels(node) Get all labels for a node
has_label(node, label) Check if node has a specific label

Label examples:

-- Get all labels
MATCH (u:User {name: 'Alice'})
RETURN labels(u) AS all_labels

-- Filter by label presence
MATCH (u)
WHERE 'Admin' IN labels(u)
RETURN u.name

-- Multi-label node matching
MATCH (u:User:Admin:Premium)
RETURN u.name

Path

Function Description
shortestPath(pattern) Find shortest path between nodes
allShortestPaths(pattern) Find all shortest paths
length(path) Get path length
nodes(path) Get nodes in path
relationships(path) Get relationships in path
start_node(path) Get starting node
end_node(path) Get ending node

Aggregate

Function Description
COUNT(*) Count rows
COUNT(expr) Count non-null values
SUM(expr) Sum of values
AVG(expr) Average of values
MIN(expr) Minimum value
MAX(expr) Maximum value
COLLECT(expr) Collect into array

String

Function Description
toString(expr) Convert to string
UPPER(string) Uppercase
LOWER(string) Lowercase
SUBSTRING(string, start, length) Extract substring
LENGTH(string) String length
TRIM(string) Remove whitespace

Mathematical

Function Description
ABS(expr) Absolute value
CEIL(expr) Round up
FLOOR(expr) Round down
ROUND(expr) Round to nearest
SQRT(expr) Square root
POW(base, exp) Power
LOG(expr) Natural logarithm
LOG10(expr) Base-10 logarithm
EXP(expr) Exponential
SIN(expr) Sine
COS(expr) Cosine
TAN(expr) Tangent

List

Function Description
size(list) List length
head(list) First element
last(list) Last element
tail(list) All but first element
[elem IN list WHERE predicate] List comprehension
extract(var IN list | expr) Transform list

CASE

Full conditional logic support in queries.

-- Simple CASE expression
MATCH (u:User)
RETURN u.name,
  CASE u.age
    WHEN 18 THEN 'Adult'
    WHEN 65 THEN 'Senior'
    ELSE 'Other'
  END AS category

-- Generic CASE expression
MATCH (u:User)
RETURN u.name,
  CASE
    WHEN u.age < 18 THEN 'Minor'
    WHEN u.age >= 18 AND u.age < 65 THEN 'Adult'
    ELSE 'Senior'
  END AS life_stage

Patterns

Pattern Comprehensions

Create collections from graph patterns:

-- Single-node comprehension
MATCH (u:User)
RETURN [(u)-[:FRIENDS_WITH]->(f) | f.name] AS friend_names

-- Relationship pattern with WHERE clause
MATCH (u:User)
RETURN [(u)-[:FRIENDS_WITH]->(f) WHERE f.age > 25 | f.name] AS older_friends

-- Multi-hop pattern comprehensions
MATCH (u:User)
RETURN [(u)-[:KNOWS]->(f)-[:FOLLOWS]->(ff) | ff.name] AS friends_of_friends

-- Outer variable scope
MATCH (u:User {name: 'Alice'})
WHERE u.age > 30
RETURN [(u)-[:KNOWS]->(f) WHERE f.age > u.age - 5 | f.name] AS peers

Map Literals

Create maps (objects) in queries:

-- Simple map
RETURN {name: 'Alice', age: 30, active: true} AS user_data

-- Map with expressions
MATCH (u:User)
RETURN {name: u.name, is_adult: u.age >= 18} AS user_info

-- Nested maps
MATCH (u:User)-[:KNOWS]->(f:User)
RETURN {
  user: u.name,
  friend: {
    name: f.name,
    age: f.age
  }
} AS relationship

Variable-Length Paths

-- 1 to 3 hops
(u)-[:KNOWS*1..3]->(v)

-- Any length
(u)-[:KNOWS*]->(v)

-- Exactly 2 hops
(u)-[:KNOWS*2]->(v)

Shortest Path

Find the shortest path between two nodes:

-- Basic shortest path
MATCH p = shortestPath(
  (a:User {name: 'Alice'})-[:KNOWS*]-(b:User {name: 'Bob'})
)
RETURN p

-- Limit path length
MATCH p = shortestPath(
  (a:User {name: 'Alice'})-[:KNOWS*..5]-(b:User {name: 'Bob'})
)
RETURN length(p) AS hops, [node IN nodes(p) | node.name] AS path

-- Get all shortest paths at minimum length
MATCH p = allShortestPaths(
  (a:User {name: 'Alice'})-[:KNOWS*..3]-(b:User {name: 'Bob'})
)
RETURN [node IN nodes(p) | node.name] AS path

Relationship directions:

-- Outgoing only
MATCH p = shortestPath((a)-[:FOLLOWS*]->(b))

-- Incoming only
MATCH p = shortestPath((a)<-[:FOLLOWS*]-(b))

-- Undirected (any direction)
MATCH p = shortestPath((a)-[:KNOWS*]-(b))

Optional Match

MATCH (u:User)
OPTIONAL MATCH (u)-[:KNOWS]->(f:User)
RETURN u.name, f.name

Parameters

Use parameters to avoid Cypher injection and improve performance:

// Named parameters
await conn.query(`
  MATCH (u:User {name: $name})
  RETURN u
`, { name: 'Alice' });

// Numbered parameters
await conn.query(`
  MATCH (u:User {name: $1})
  RETURN u
`, ['Alice']);

Examples

Find friends of friends

MATCH (me:User {name: 'Alice'})-[:KNOWS]->(friend)-[:KNOWS]->(foaf:User)
WHERE NOT (me)-[:KNOWS]->(foaf) AND me <> foaf
RETURN foaf.name, COUNT(friend) AS mutual_friends
ORDER BY mutual_friends DESC
LIMIT 10

Find users by age range

MATCH (u:User)
WHERE u.age >= 25 AND u.age < 35
RETURN u.name, u.age
ORDER BY u.age
MATCH (d:Document)
RETURN d.title, d.embedding <-> $query AS distance
ORDER BY distance
LIMIT 5

Aggregation

MATCH (u:User)-[:KNOWS]->(f:User)
RETURN u.name, COUNT(f) AS friend_count, AVG(f.age) AS avg_friend_age
ORDER BY friend_count DESC

See Also