Skip to main content

Querying LoraDB with Cypher

LoraDB speaks a pragmatic subset of Cypher. Queries are strings that chain clauses — see the clause reference below, or jump into the Ten-Minute Tour for a guided run-through.

MATCH  (p:Person)-[:WORKS_AT]->(c:Company)
WHERE  p.active = true
RETURN p.name, c.name
ORDER  BY p.name

Each clause reads the rows emitted by the previous one and passes rows forward. RETURN ends the pipeline.

Anatomy of a query

MATCH — find patterns (produces rows)

WHERE — filter rows (drops rows)

WITH — project + optionally group (reshapes rows)

WHERE — filter rows post-aggregate (HAVING-style)

RETURN — project + sort + paginate (final shape)

Not every query uses every stage. The important invariant: each clause sees the rows produced by the previous one.

Clause reference

ClausePurpose
MATCHFind patterns of nodes and relationships
CREATECreate nodes and relationships
WHEREFilter rows
IndexesDeclare, inspect, query, and drop secondary indexes
ConstraintsAdd uniqueness, existence, key, and type checks
RETURN / WITHProject, rename, order, and page results
ORDER BY / SKIP / LIMITSort and paginate
SET / REMOVE / DELETEMutate existing entities
UNWIND / MERGEIterate over lists; create-or-match
Aggregationcount, collect, avg, and group-by
PathsVariable-length traversals and shortest paths

For copy-paste examples covering every clause, see Query Examples. For a single-page terse reference, see the Cheat sheet.

Where common tasks live

TaskPage
Look up by label + propertyMATCH
Write new nodes/edgesCREATE
UpsertMERGE
Bulk importUNWIND + CREATE
Patch a property mapSET +=
Replace all propertiesSET =
Remove a propertyREMOVE / SET n.p = null
Delete with edgesDETACH DELETE
Top-NORDER BY + LIMIT
Stable paginationKeyset pagination
Group and aggregateAggregation walkthrough
HAVING-style filterWITH WHERE
Anti-joinNOT EXISTS
Speed up common predicatesCREATE INDEX
Enforce uniqueness or property shapeCREATE CONSTRAINT
Shortest pathshortestPath
Inline related listPattern comprehension
Per-row conditional valueCASE expressions
Count rows matching a conditioncount(CASE WHEN THEN 1 END)

Execution model

  • Queries execute atomically per auto-commit call. Rust and in-process bindings also expose explicit transactions; HTTP does not.
  • Auto-commit reads can overlap on Arc snapshots. Write commits and explicit read-write transactions serialize. See Limitations → Concurrency.
  • Names (labels, relationship types, property keys) are validated against the live graph for MATCH; any name is accepted by CREATE, MERGE, and SET.
  • Unknown function names are rejected at analysis time — see Functions.

Parameters

Any value that isn't a constant should use a parameter. The short version follows; Parameters has the full reference.

MATCH (p:Person) WHERE p.name = $name RETURN p

Parameters are bound at call time from the host language:

Missing parameters resolve to null, which can silently produce empty results — set them or validate inputs before executing.

Parameters vs inline literals

// Safe (parameterised)
MATCH (u:User) WHERE u.id = $id RETURN u

;// Unsafe if $id came from untrusted input and was inlined
MATCH (u:User) WHERE u.id = 42 RETURN u

Parameters are the only supported way to mix untrusted input into a query. They also let the query planner cache plans across invocations.

Parameter types

Host valueLoraDB type
null / None / undefinedNull
boolBoolean
int (Python) / number (JS, integer) / i64 (Rust)Integer
float (Python) / number (JS, non-integer) / f64 (Rust)Float
str / StringString
list / array / VecList
dict / object / BTreeMapMap
host helpers (date(), wgs84(), …)Date, Point, etc.

Host helpers are binding APIs. In query text, use cast syntax for typed construction, for example '2026-05-01'::DATE or {x: 1, y: 2}::POINT.

What's not supported

See Limitations for the full list. Short version: no general-purpose CALL, no FOREACH, no LOAD CSV, and no multi-database (USE). Index and constraint DDL are supported for scoped catalog entries; see Indexes and Constraints.

See also