Skip to content

Read queries

This page walks the read side of Cypher in NamiDB, with examples that all run on the current engine.

MATCH

MATCH (p:Person) RETURN p.name LIMIT 10

MATCH (n) without a label fans out across every label observed in the namespace (memtable + persisted SSTs + declared schema).

MATCH (n) RETURN labels(n), count(*) AS n

Pattern matching

MATCH (a:Person {name: $name})-[:KNOWS]->(b:Person)
RETURN b.name AS friend

Property predicates lifted into the curly-brace pattern are pushed down to the SST scan and used for bloom-filter / fence-pointer pruning.

Variable-length paths

MATCH (a:Person {_id: $start})-[:KNOWS*1..3]->(b)
RETURN DISTINCT b.name AS friend_of_friend

The depth bounds (1..3) are required — unbounded * is not in scope.

Filters

MATCH (p:Person)
WHERE p.age >= $min AND p.country IN ['EC', 'SV']
RETURN p.name AS name, p.age AS age
ORDER BY p.age DESC
LIMIT 100

Predicates are pushed down through joins (RFC-011) and through Parquet row-group pruning (RFC-013).

Optional match

MATCH (p:Person {_id: $id})
OPTIONAL MATCH (p)-[:OWNS]->(c:Car)
RETURN p.name AS name, collect(c.model) AS cars

c.model will be null/empty if no OWNS edge exists.

Existence subqueries

MATCH (p:Person)
WHERE EXISTS {
MATCH (p)-[:WORKS_AT]->(:Company {country: $country})
}
RETURN p.name

EXISTS { ... } decorrelates into a hash semi-join (RFC-014) — no nested loop required.

Aggregations

MATCH (p:Person)-[:KNOWS]->(b)
RETURN p.country AS country, count(DISTINCT b) AS reach
ORDER BY reach DESC
LIMIT 20

Vectorised aggregation runs morsel-at-a-time; group-by uses a hash-aggregator.

EXPLAIN

EXPLAIN VERBOSE
MATCH (a:Person)-[:KNOWS]->(b) RETURN b ORDER BY b.id LIMIT 20

prints the chosen logical plan with selectivity and cost annotations, plus the physical-operator tree.

Terminal window
namidb explain --verbose "MATCH (a:Person)-[:KNOWS]->(b) RETURN b LIMIT 5"

See also