Docs
View as markdown

relate query

The relate query command with its three session forms, every query-run flag, output modes in brief, parameters, read-only opens, timeouts and exit codes.

cli

relate query runs a statement session against one store: the statements given as an argument, a script read from stdin, or the interactive shell. It takes every query-run flag. The path-first form, relate [OPTIONS] [QUERY], runs the same session with the same flags; the one difference is that it never reads a script from stdin. Without --database, the store is :memory:, which is gone when the process exits. A query A statement that reads, where the contrast with writing matters; also relate query, the command that runs a statement session. Read more in the glossary, in these docs, is a statement that reads; the command runs writes too.

Synopsis

relate query [STATEMENT] [--database PATH]
PartMeaning
STATEMENTOne Cypher statement, or a list separated by ;. Optional. -c and --command are the flag spelling of the same argument
--database PATHThe store: a directory, a path ending in .rl, or :memory: (the default). Never a URL; a remote store is a --load source. Short form -d
OPTIONSAny query-run flag, before or after STATEMENT (Options)

The word query is the command when it is the first positional argument, before or after flags; a later positional query is an unexpected argument (exit code 2). A directory named query is --database ./query.

Options

relate query takes the query-run flags, the same set as the path-first form. A flag beats its environment variable, which beats the built-in default. Flags may come before or after the statement, a flag's value is the next argument (--mode envelope, not --mode=envelope), and --read-only is the one flag whose value is attached (--read-only=live). -- ends the options: every argument after it is positional, so a statement that starts with - can follow it. How flags are parsed has every parsing rule, and Environment variables lists the variables.

FlagArgumentDefaultScopeSinceDescription
--database, -dPATH:memory:query run—The store target: a directory, a .rl file (legacy .cl files still open), or :memory:. Never a URL; a remote store is a --load source.
--command, -cCYPHERunsetquery run—One statement or a ;-separated list; the same as the positional QUERY, and the two cannot be combined.
--loadSOURCEunsetquery run—Load a store's content from a source (a local .rl file, a directory, or an http(s) URL to a .rl file) into the target: into :memory: it is an ephemeral read-only open; into a new -d PATH it creates the store.
--modeMODEtable on a terminal; jsonl when stdout is piped or redirected; toon instead of jsonl when agent mode is onquery run—Output mode: table, csv, json, jsonl, envelope, markdown, cypher, toon, speedscope. An explicit mode always overrides the default.
--formatMODEas --modequery run—Alias of --mode (the neo4j-cli spelling). --output and -o are unknown flags whose did-you-mean names --format.
--json
also -json
—offquery run—Shortcut for --mode json: one object per result set with the rows in data; indented on a terminal, one compact line when piped.
--csv
also -csv
—offquery run—Shortcut for --mode csv.
--jsonl
also -jsonl
—offquery run—Shortcut for --mode jsonl.
--markdown
also -markdown
—offquery run—Shortcut for --mode markdown.
--toon—offquery run—Shortcut for --mode toon.
--pretty—offquery run—Force indented json output when stdout is not a terminal; ignored by the other modes.
--noheader
also -noheader
—offquery run—Suppress column headers.
--param
also -param
N=Vunsetquery run—Bind a Cypher parameter (repeatable). A value that parses as JSON keeps its JSON type (true, null and numbers included); a value that starts with a digit, -, ", [ or { and does not parse exits 2; any other value binds as a string.
--fetch-paramsN=SRCunsetquery run—Fetch an http(s) URL or read a file, parse it as JSON, and bind it as parameter N (repeatable; 64 MiB cap, 60 s timeout). A CLI-process fetch with no URL allowlist.
--snapshot-formatparquet|json|markdown|parquet-wideparquet (json in builds without the parquet feature)query run—Snapshot codec for an empty directory; an existing store keeps its recorded codec, and a different codec fails the open (exit 1). parquet-wide is the parquet codec with one typed column per common property key (format version 5): on an empty directory it creates a wide store, on an existing parquet store the next checkpoint re-encodes every part, and the manifest keeps the store wide after that.
Environment: RELATE_SNAPSHOT_FORMAT.
--markdown-body-propertiesLISTbodyquery run—Body properties of a markdown-codec store (LIST or Label=LIST; entries separated by ;; the first is written bare, the rest as ## sections).
--wal-dirPATH<DATABASE>/walquery run—Local WAL directory for a directory store; rejected for .rl files.
--checkpoint-interval-secsN300query run—Timed checkpoint period; 0 disables the timer. Persistent stores only.
Environment: RELATE_CHECKPOINT_INTERVAL_SECS.
--durability-modefull|everysecond|snapshotfullquery run—Commit durability policy. everysecond can lose about the last second of acknowledged writes in a crash; snapshot can lose every write since the last completed checkpoint.
Environment: RELATE_DURABILITY_MODE.
--logical-graph-size-limitSIZEunlimitedquery run—Live graph and index cap in logical bytes; 0 or unset is unlimited.
Environment: RELATE_LOGICAL_GRAPH_SIZE_LIMIT.
--expression-memory-limitSIZE256 MiBquery run—Per-allocation expression cap; none or 0 disables it.
Environment: RELATE_EXPRESSION_MEMORY_LIMIT.
--concurrent-logical-workspace-limitSIZEadmission offquery run—Shared logical-workspace pool; a positive value turns query admission on; 0 is rejected.
Environment: RELATE_CONCURRENT_LOGICAL_WORKSPACE_LIMIT.
--max-traversal-depthN500query run—Largest explicit traversal hop bound (1 through 2000); a larger bound fails at admission with TraversalDepthExceeded.
Environment: RELATE_MAX_TRAVERSAL_DEPTH.
--safe, --no-safe—offquery run—Opt-in safe mode: refuses a new named node without a label, and a MATCH read whose final RETURN/WITH has no LIMIT and no reducing aggregate, as SafeModeViolation (exit 6).
Environment: RELATE_SAFE_MODE.
--timeoutDURATIONunset (no bound)query run—Per-statement wall-clock bound: a bare number is seconds, ms/s/m suffixes, fractions allowed; 0 disables. A timed-out statement exits 7 with code: "timeout".
--max-rowsN100 under a detected agent harness with stdout not a terminal; otherwise unlimitedquery run—Rows printed per statement; 0 is unlimited. A cut result warns on stderr, names the cut in-band in the machine modes, and exits 0.
Environment: RELATE_MAX_ROWS.
--widthNthe terminal width, else COLUMNS, else the natural widthquery run—Wrap the human table output to N columns; a value under 20 exits 2.
--read-only[=snapshot|live]offquery run—Open an existing store without writing, checkpointing or migrating. snapshot (default) freezes the state at open; live tails a directory store's WAL (refused for .rl and :memory:). Attached form only; once only. A write fails with exit 6.
--load-csv-dirPATHdeniedquery run—Allow local LOAD CSV only for regular files under this directory; per-file limit 8 MiB.
Environment: RELATE_LOAD_CSV_DIR.
--namespaceNAMEneo4jquery run—Session namespace for the run: neo4j, system or system_ontologies (case-insensitive). Not accepted by pull.
--agent-mode, --no-agent-mode—detected (stdout not a terminal and an agent harness variable set)query run—Turn agent ergonomics (the row-cap default and the piped toon default) on or off unconditionally; overrides RELATE_AGENT_MODE and detection.
Environment: RELATE_AGENT_MODE.
--help, -h——query run—Print usage to stdout and exit 0; after a command word, that command's help.
--version
also -version, -v
——query run—Print Relate v<version> and License: Apache 2.0 (binary); with --json, one JSON object with arch, license, name, os, version.
--——query run—Treat all following arguments as positional.

A — under Since: the data does not record the release that added the flag.

Session forms

The form depends on whether a statement is given and on what stdin is:

FormChosen whenRuns
OneshotSTATEMENT or -c is givenThe statement, or each statement of the ;-separated list in order, then exits
Stdin scriptNo statement, and stdin is a pipe, a file or /dev/nullEvery statement on stdin until end of input, then exits. Statements end with ; (the last one may omit it), may span lines, and // starts a comment. Dot commands such as .begin and .commit work one per line
Interactive shellNo statement, and stdin is a terminalA prompt with readline-style editing and the dot commands, until .quit or end of input

In the oneshot and stdin forms, each statement prints its own result set and commits on its own, unless a .begin in a script opened a transaction A unit of work that commits as a whole or not at all; each statement is its own transaction unless an explicit begin … commit groups several. Read more in the glossary. A failed statement stops the run: the statements before it stay committed, and the rest do not run. Dot commands lists the shell and script commands, and Use the interactive shell covers the shell.

The path-first form with no statement differs only in the stdin case: it prints the top-level help and exits 0 without reading stdin, so a redirected script never runs. A script on stdin needs the word query.

InputExit codeMessage on stderr
STATEMENT and -c together2Error: --command cannot be combined with a positional query
A second positional statement2Error: unexpected argument: <statement>, the usage line, and a --help hint
Empty stdin0None

These examples run in a new, empty directory. This first command writes: it creates team.rl, a single-file store holding three people and two projects, and prints nothing, because a CREATE with no RETURN has no rows:

relate query --database ./team.rl "CREATE (ada:Person {name: 'Ada', role: 'engineer'}),
       (grace:Person {name: 'Grace', role: 'engineer'}),
       (noor:Person {name: 'Noor', role: 'maintainer'}),
       (relate:Project {name: 'relate', language: 'Rust'}),
       (tck:Project {name: 'opencypher-tck', language: 'Gherkin'}),
       (ada)-[:WORKS_ON {since: 2024}]->(relate),
       (grace)-[:WORKS_ON {since: 2023}]->(relate),
       (grace)-[:WORKS_ON {since: 2022}]->(tck),
       (noor)-[:MAINTAINS]->(relate),
       (ada)-[:KNOWS]->(grace)"

A oneshot read. Stdout is a pipe here, so the output mode is jsonl: one JSON object per row, then one line with the statement's timings and plan-cache outcome:

relate query --database ./team.rl --read-only "MATCH (p:Person) RETURN p.name AS name ORDER BY name"
{"name":"Ada"}
{"name":"Grace"}
{"name":"Noor"}
{"planCache":"miss","timings":{"elapsed_ms":0.532833,"execute_ms":0.366083,"lex_parse_ms":0.028334,"lower_ms":0.042624999999999996,"parse_ms":0.104958,"plan_ms":0.052958,"result_generation_ms":0.000167,"rewrite_ms":0.008209000000000001}}

-c with a ;-separated list prints one result set per statement, here as envelopes (--mode envelope):

relate query --database ./team.rl --read-only --mode envelope -c "MATCH (p:Person) RETURN count(p) AS people; MATCH (p:Project) RETURN count(p) AS projects"
{"columnTypes":["INTEGER"],"columns":["people"],"notifications":[],"planCache":"miss","rows":[{"people":3}],"timings":{"elapsed_ms":0.46900000000000003,"execute_ms":0.299875,"lex_parse_ms":0.030875,"lower_ms":0.041832999999999995,"parse_ms":0.106041,"plan_ms":0.055,"result_generation_ms":0.000375,"rewrite_ms":0.008542000000000001},"truncated":false}
{"columnTypes":["INTEGER"],"columns":["projects"],"notifications":[],"planCache":"miss","rows":[{"projects":2}],"timings":{"elapsed_ms":0.032499999999999994,"execute_ms":0.004459,"lex_parse_ms":0.0055,"lower_ms":0.009209,"parse_ms":0.019167,"plan_ms":0.007541,"result_generation_ms":0.000084,"rewrite_ms":0.00041600000000000003},"truncated":false}

The same two statements as a script on stdin:

printf 'MATCH (p:Person) RETURN count(p) AS people;\nMATCH (p:Project) RETURN count(p) AS projects;\n' | relate query --database ./team.rl --read-only --mode envelope
{"columnTypes":["INTEGER"],"columns":["people"],"notifications":[],"planCache":"miss","rows":[{"people":3}],"timings":{"elapsed_ms":0.468375,"execute_ms":0.283959,"lex_parse_ms":0.028917,"lower_ms":0.052667000000000005,"parse_ms":0.1175,"plan_ms":0.058708,"result_generation_ms":0.00025,"rewrite_ms":0.008084},"truncated":false}
{"columnTypes":["INTEGER"],"columns":["projects"],"notifications":[],"planCache":"miss","rows":[{"projects":2}],"timings":{"elapsed_ms":0.043417000000000004,"execute_ms":0.003333,"lex_parse_ms":0.007666999999999999,"lower_ms":0.010875,"parse_ms":0.02575,"plan_ms":0.011916999999999999,"result_generation_ms":0.000083,"rewrite_ms":0.00075},"truncated":false}

A script that fails at its second statement. The first statement's result prints, the stderr lines say how far the run got, and the error object names the statement:

printf 'MATCH (p:Person) RETURN count(p) AS people;\nRETURN 1/0 AS boom;\nRETURN 3 AS never;\n' | relate query --database ./team.rl --read-only --mode envelope
echo "exit=$?"
{"columnTypes":["INTEGER"],"columns":["people"],"notifications":[],"planCache":"miss","rows":[{"people":3}],"timings":{"elapsed_ms":0.315917,"execute_ms":0.148167,"lex_parse_ms":0.028875,"lower_ms":0.042959,"parse_ms":0.104167,"plan_ms":0.055542,"result_generation_ms":0.00025,"rewrite_ms":0.008542000000000001},"truncated":false}
type error: / by zero
statement 2 of 3 failed; 1 completed and committed; 1 not run
{"error":{"code":"validation_error","committed":1,"exit_code":6,"kind":"type","message":"type error: / by zero","retryable":false,"statement":2,"statements":3}}
exit=6

Output modes

Without an output flag, the mode depends on where stdout goes:

stdoutDefault mode
A terminaltable
A pipe or a filejsonl
A pipe or a file, with agent mode ontoon

--mode (alias --format) picks one of table, csv, json, jsonl, envelope, markdown, cypher, toon and speedscope; --json, --csv, --jsonl, --markdown and --toon are shortcuts. Of several output flags, the last one wins. A failed statement prints the error object on stdout in envelope, json, jsonl and speedscope; table, csv, markdown, cypher and toon print nothing on stdout; the stderr message and the exit code remain. Output modes shows each mode's output.

--mode table on the people in team.rl:

relate query --database ./team.rl --read-only --mode table "MATCH (p:Person) RETURN p.name AS name, p.role AS role ORDER BY name"
+---------+--------------+
| name    | role         |
+---------+--------------+
| "Ada"   | "engineer"   |
| "Grace" | "engineer"   |
| "Noor"  | "maintainer" |
+---------+--------------+

Parameters

A statement reads a parameter A named value a statement refers to as $name and the caller binds separately, such as with --param name=value on the CLI. Read more in the glossary as $name. Two flags bind them, and both repeat, one parameter each:

FlagBindsLimits
--param N=V$N to V, parsed as JSON. A value that starts like JSON (a digit, -, ", [ or {) and does not parse exits 2; any other bare word is a stringA name bound twice keeps the last value
--fetch-params N=SRC$N to the JSON parsed from SRC: a file path, or an http or https URL64 MiB per source and 60 seconds per fetch. No URL allowlist: the fetch has the same trust as --param

A statement that names a parameter no flag bound fails with semantic error: ParameterMissing: Expected parameter(s): <name> and exit code 6. Grace's projects, by parameter, against team.rl:

relate query --database ./team.rl --read-only --mode envelope --param name=Grace 'MATCH (p:Person {name: $name})-[w:WORKS_ON]->(r:Project) RETURN r.name AS project, w.since AS since ORDER BY since'
{"columnTypes":["STRING","INTEGER"],"columns":["project","since"],"notifications":[],"planCache":"miss","rows":[{"project":"opencypher-tck","since":2022},{"project":"relate","since":2023}],"timings":{"elapsed_ms":0.473833,"execute_ms":0.281583,"lex_parse_ms":0.033209,"lower_ms":0.047208,"parse_ms":0.12095800000000001,"plan_ms":0.06224999999999999,"result_generation_ms":0.00029099999999999997,"rewrite_ms":0.008124999999999999},"truncated":false}

Single quotes keep the shell from expanding $name. Script the CLI shows typed values and a JSON file.

Read-only opens

--read-only opens an existing store without writing or checkpointing it. It is off unless given, and it may appear once per run.

SpellingOpensRefused for
--read-only, --read-only=snapshotThe store as it was at open: a frozen snapshot. On a directory store it can open beside a writer; a .rl file opens only while no writer holds it—
--read-only=liveA live read-only open: it tails the WAL and follows the writer's commits.rl files and :memory:: semantic error: live freshness (WAL follow) is only supported for native directory databases, exit code 1
--read-only live (a space)Nothing: exit code 2 with Error: --read-only takes its value attached: --read-only=live—

A read-only open never creates a store. A missing directory fails with storage error: read-only open requires an existing database at <path> and a missing .rl file with storage error: database not found: <path>, each after Failed to open Relate: and with exit code 1. On :memory:, --read-only rejects writes and creates nothing. A write against a read-only open fails before it changes anything, with exit code 6:

relate query --database ./team.rl --read-only --mode envelope "CREATE (:Person {name: 'Zed'})"
echo "exit=$?"
semantic error: WriteOnReadOnlyAccessDatabase: No write operations are allowed on this database. The database is in read-only mode on this Neo4j instance.
{"error":{"code":"validation_error","exit_code":6,"kind":"semantic","message":"semantic error: WriteOnReadOnlyAccessDatabase: No write operations are allowed on this database. The database is in read-only mode on this Neo4j instance.","retryable":false}}
exit=6

Statement timeouts

--timeout DURATION bounds each statement's wall-clock time on its own. A bare number is seconds; ms, s and m suffixes and fractions are accepted; 0 turns the bound off. Unset, a statement has no time bound. A statement that runs longer is cancelled and exits 7; the error object's code is timeout and retryable is false:

relate query --read-only --mode envelope --timeout 100ms "UNWIND range(1, 20000) AS a UNWIND range(1, 20000) AS b RETURN count(*) AS pairs"
echo "exit=$?"
Error: query timed out after 100ms
{"error":{"code":"timeout","exit_code":7,"kind":"execution","message":"query timed out after 100ms","retryable":false}}
exit=7

A value that is not a duration exits 2 with Error: invalid --timeout: '<value>' is not a duration (try 500ms, 10s, 2m).

Errors and exit codes

A session exits with the code of the first statement that failed, or 0. An empty result is a success.

Exit codeMeaning in a query session
0Every statement ran, including one with no rows
1Runtime failure: the store did not open, a capacity limit, an I/O or internal error
2Usage error: unknown flag, bad or missing value, extra positional; nothing ran
5Conflict: another process holds the store for writing, or a write-write conflict
6The statement was rejected: syntax, semantic or type error, or a write on a read-only open
7A statement exceeded --timeout

The exit codes page has the error object's fields and a recorded run for each code.

Examples

Who works on what, written to a CSV file with a header row:

relate query --database ./team.rl --read-only --csv "MATCH (p:Person)-[w:WORKS_ON]->(r:Project) RETURN p.name AS person, r.name AS project, w.since AS since ORDER BY since" > who.csv
echo "exit=$?"
cat who.csv
exit=0
person,project,since
Grace,opencypher-tck,2022
Grace,relate,2023
Ada,relate,2024

See also

  • CLI flags: each query-run flag with its environment variable
  • Script the CLI: stdin scripts, parameters, timeouts, and exit codes in shell scripts
  • Dot commands: .begin, .commit and the other shell and script commands
  • Agent mode: the row cap and the toon default under an agent harness
  • relate agent-context: the flag names and exit codes as a compact briefing