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

Command-Line Interface

patinadb operates on an embedded database directory. The first argument is always the database path; the rest is a subcommand.

patinadb <db-path> <subcommand> [args]

If you’re running it from the Docker image rather than a host-installed binary: docker run -v "$PWD:/data" --entrypoint patinadb patinadb/patinadb /data/<db-path> <subcommand> [args]. See Installation.

Subcommands

query

Execute a Cypher query and print the results.

patinadb ./mygraph query "MATCH (n:Person) RETURN n LIMIT 10"
patinadb ./mygraph query "MATCH (n) RETURN n" --json
patinadb ./mygraph query "MATCH (n) RETURN n" --at <engram-id>
FlagEffect
--jsonEmit results as JSON instead of a human-readable table.
--at <id>Time-travel: run against the graph at that engram.

import

Offline bulk-load neo4j-admin-style CSV / Parquet / Arrow IPC files straight into the embedded store (bypasses Raft + the engram/versioning layer — fast, but the loaded data is HEAD-visible only, not in --at history). All node files load first, then all relationship files.

patinadb ./mygraph import --nodes people.csv --nodes companies.parquet \
                          --rels works_at.arrow
patinadb ./mygraph import --nodes n.csv --rels r.csv --id-type uuid

Node files carry a :ID column, a :LABEL column, and typed property columns (name:int, name:float, name:boolean, name:date, name:localdatetime, or bare name for string). Relationship files carry :START_ID/:END_ID/:TYPE

  • property columns. For Parquet/Arrow the property types come from the file schema. A blank/null cell means the property is absent.
FlagDefaultEffect
--nodes <file>A node file (repeatable).
--rels <file>A relationship file (repeatable).
--format <fmt>(infer)Force csv|parquet|arrow for all files (else per extension).
--delimiter <c>,CSV field delimiter.
--batch-size <n>10000Rows per durable batch.
--skip-ref-checkoffDon’t verify rel endpoints exist (allows dangling edges).
--id-type <t>hashhash = UUIDv5 of the id string; uuid = the id cell IS the UUID.

--id-type uuid (and an auto-detected :ID(uuid) header) treat the id column as a literal vertex UUID — this is what lets exportimport reproduce the same graph.

export

The complement of import: scan the whole graph read-only and write import-compatible node/relationship files. One node file per primary label (nodes_<Label>.<ext>) and one relationship file per edge type (rels_<TYPE>.<ext>) are written into --out, streamed in --batch-size batches (bounded memory).

patinadb ./mygraph export --out ./dump
patinadb ./mygraph export --out ./dump --format parquet
patinadb ./mygraph export --out ./dump --format arrow --batch-size 50000
FlagDefaultEffect
--out <dir>Output directory (created if missing).
--format <fmt>csvcsv, parquet, or arrow.
--batch-size <n>10000Rows per output batch (columnar formats).

Round-trip: the id column is written as the raw vertex UUID under an :ID(uuid) header, so re-importing the dump reproduces the same graph, the same UUIDs included (no re-keying):

patinadb ./mygraph export --out ./dump --format parquet
patinadb ./fresh.db import --nodes ./dump/nodes_Person.parquet \
                           --rels  ./dump/rels_KNOWS.parquet

Typed properties round-trip through the columns: Integer→:int, Float→:float, Bool→:boolean, String, Date→:date, LocalDateTime→:localdatetime (Parquet/ Arrow use the native Int64/Float64/Boolean/Date32/Timestamp types). A property that appears as mixed types across a label promotes (Int+Float→Float) or, if incompatible, is written as a string column. Zoned/offset datetimes, times, and durations are exported as ISO-8601 strings (they have no lossless columnar type).

backup / restore

Portable dump and restore of one embedded database. backup writes a single self-contained file (the graph plus compound-index and UNIQUE-constraint defs); restore rebuilds a target database directory (fresh or existing) from it. This is the embedded/offline analogue of the server’s GET /mgmt/snapshot + POST /mgmt/restore.

patinadb ./mygraph backup ./mygraph.bak
patinadb ./mygraph backup ./mygraph.bak --history   # + engram timeline (PITR)
patinadb ./fresh.db restore ./mygraph.bak
patinadb ./existing.db restore ./mygraph.bak --force   # overwrite a non-empty target
FlagEffect
--historyAlso carry the full engram delta/snapshot timeline (backup only).
--forceRequired to restore into a non-empty target database (restore only).

restore refuses to silently overwrite a non-empty target. Before opening the backup file at all, it opens the target and cheaply checks its node/edge counts; if the target already holds data and --force wasn’t passed, it dies with a clear target db <path> is not empty (N nodes, M edges) — pass --force to overwrite and touches nothing (no file is opened, no data is changed). An empty or not-yet-created target restores with no flag needed — this only guards against accidentally pointing restore at the wrong, already-populated directory (mirroring neo4j-admin’s --overwrite-destination convention). A corrupt or truncated backup file also fails cleanly with a clear message (never a panic), whether or not --force is given.

Without --history the backup is a HEAD-state dump — the current graph only. With --history it additionally carries the engram history, so after restore the whole pre-backup timeline is available for time-travel:

patinadb ./mygraph backup ./mygraph.bak --history
patinadb ./fresh.db restore ./mygraph.bak
patinadb ./fresh.db query "MATCH (n) RETURN count(n)" --at <old-engram-id>

changes

Print the change log — every committed engram after a cursor (oldest first), each rendered as its individual mutations (createNode, setNodeProperty, createRel, …). The embedded/offline analogue of the server’s /changes stream.

patinadb ./mygraph changes                       # whole history
patinadb ./mygraph changes --since <engram-id>   # only what changed after the cursor
patinadb ./mygraph changes --json
FlagEffect
--since <id>Only engrams committed after this engram UUID (a cursor).
--jsonOne JSON object per engram, with a changes array.

Each engram’s own id is a valid --since cursor for the next call, so a script can poll incrementally by remembering the last id it saw. (A built-in --follow is intentionally not offered: an embedded database is exclusively locked by its single process, so there is no concurrent writer for one to tail.)

algo

Run a graph algorithm via CALL patinadb.algo.* and print the top-k ranked table (node id + value, highest first) — a convenience over typing the full CALL.

patinadb ./mygraph algo pageRank --label Person --rel KNOWS --limit 10
patinadb ./mygraph algo wcc
patinadb ./mygraph algo degree --label Person

<name> is one of pageRank, wcc, degree, betweenness, closeness, triangleCount, labelPropagation (case-insensitive).

FlagDefaultEffect
--label <L>(all)Restrict to nodes with this label.
--rel <R>(all)Restrict to relationships of this type.
--limit <k>20Number of top-ranked rows to print.

Spatial queries and constraints are already reachable through query, e.g. query "CREATE CONSTRAINT FOR (p:Person) REQUIRE p.email IS UNIQUE" or query "MATCH (p:Place) WHERE point.distance(p.loc, point({latitude:52.5, longitude:13.4})) < 5000 RETURN p".

log

List committed engrams (the history).

patinadb ./mygraph log

diff

Git-style view of a single engram.

patinadb ./mygraph diff <engram-id>
patinadb ./mygraph diff <engram-id> --json

diff-range

Structural, move-aware diff between two engrams (or from the empty graph).

patinadb ./mygraph diff-range <from-id> <to-id>
patinadb ./mygraph diff-range empty <to-id>
patinadb ./mygraph diff-range <from> <to> --identity-props email,id
patinadb ./mygraph diff-range <from> <to> --json
FlagDefaultEffect
--identity-props <list>qualified_name,fqn,nameIdentity priority for move pairing; none off.
--jsonJSON output.

See Diffs and Time Travel for the concepts behind diff, diff-range, and --at.