CALL Subqueries

CALL { ... } isolates a scope and lets you compose post-aggregation logic + batch writes.

0/4 done

Overview

CALL Subqueries

CALL { ... } isolates a scope and lets you compose post-aggregation logic + batch writes.

Why it matters

Subqueries are how you write 'do this once per row' without leaving Cypher — and IN TRANSACTIONS OF N ROWS is how you safely write millions of rows in one statement.

Going deeper

CALL { ... } runs a subquery with its own scope, executed once per incoming row (when it imports variables):

MATCH (c:Customer)
CALL {
  WITH c
  MATCH (c)-[:PLACED]->(o:Order)
  RETURN sum(o.total) AS spend
}
RETURN c.name, spend ORDER BY spend DESC;

The killer feature for writes is batching:

CALL {
  MATCH (o:Order) WHERE o.archived IS NULL
  SET o.archived = false
} IN TRANSACTIONS OF 1000 ROWS;

This commits every 1000 rows, so a multi-million-row update doesn't build one giant transaction that exhausts the heap. Trade-off: atomicity is now per-batch, not whole-statement — if it fails at row 2.5M, the first 2.5M are already committed, so make the operation idempotent (re-runnable).

Analogy

A CALL { ... } subquery is a sealed workshop inside the factory. Whatever tools and mess it uses stay inside; only the finished part comes out onto the main line. That isolation is what lets you do 'once per row' work — and IN TRANSACTIONS OF N ROWS is the workshop emptying its bin every N parts so it never overflows.

Pitfalls — what breaks when this is weak

  • Expecting whole-statement atomicity with IN TRANSACTIONS. It commits per batch. Fix: make the write idempotent and resumable.
  • Forgetting WITH c to import the outer variable. The subquery can't see outer scope otherwise. Fix: import explicitly.
  • Huge batch size. Defeats the memory benefit. Fix: tune N (often 1k–10k).

Make it stick

Use the prompts below to anchor call subqueries to a real graph you own.

  • Which large write in your system risks a heap blowup and should be batched with IN TRANSACTIONS?
  • Is that write idempotent enough to survive a mid-run failure leaving earlier batches committed?
  • Where would a per-row CALL subquery replace an awkward multi-statement workaround?

Reading in progress · 0 of 4 activities done