Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cypher

Express graph patterns, filter properties, and shape tabular results with Cypher.

Conformance

OrchidDB passes all 3,897 scenarios in the pinned openCypher 2024.3 Technology Compatibility Kit. The conformance comparison includes individual outcomes, upstream assertions, execution timings, and downloadable evidence.

Match a pattern

Cypher uses parentheses for nodes and brackets for relationships. A colon names a label or relationship type, and an arrow gives direction:

MATCH (p:Person)-[:ORDERED]->(o:Order)
RETURN p.name, o.total
ORDER BY o.total

These queries use the mapped tutorial dataset. The pattern follows each person’s orders and returns the person’s name with the order total.

Filter and project

Use WHERE to select matches and AS to name result columns:

MATCH (p:Person)
WHERE p.age >= 30
RETURN p.name AS name, p.age AS age
ORDER BY age DESC

The tutorial returns carol, then alice. Use explicit column aliases for stable application-facing result names.

Read relationship properties

Bind a relationship to a variable to use its properties:

MATCH (p:Person)-[r:ORDERED]->(:Order)
WHERE r.total > 100.0
RETURN p.name, r.total
ORDER BY r.total

A mapped relationship property resolves to the column configured with EdgeMapping::property.

Aggregate matches

Non-aggregate expressions define the grouping keys:

MATCH (p:Person)-[r:ORDERED]->(:Order)
RETURN p.name AS name, sum(r.total) AS spent
ORDER BY name
namespent
alice170
bob80
carol500

Use count(...) to count matches and DISTINCT when the query should remove duplicate results.

Compose query stages

WITH introduces an intermediate projection. It is useful for filtering an aggregate before returning the final result:

MATCH (p:Person)-[:ORDERED]->(o:Order)
WITH p.name AS name, sum(o.total) AS spent
WHERE spent > 100.0
RETURN name, spent
ORDER BY spent DESC

Preserve optional matches

OPTIONAL MATCH keeps the input row when its optional pattern has no match:

MATCH (p:Person)
OPTIONAL MATCH (p)-[:FOLLOWS]->(friend:Person)
RETURN p.name, friend.name
ORDER BY p.name, friend.name

In the tutorial, carol has no outgoing FOLLOWS row, so her optional friend binding is null.

Bound a traversal

A variable-length relationship can express paths over several hops:

MATCH (p:Person)-[:FOLLOWS*1..2]->(friend:Person)
WHERE p.name = 'alice'
RETURN DISTINCT friend.name
ORDER BY friend.name

Choose explicit bounds that match the application’s question. The distinct projection returns each friend’s name once even if several paths reach that friend.

Parameters and writes

Pass application inputs through cypher_with_params and reference them as $name or $minimum. See parameters for a complete example.

For graph-owned writes, use managed graphs. For native updates over mapped tables, use update properties.