CypherService
OpenCypher-compatible query execution service.
Proto source
Transport
All methods are available via:
- gRPC on port 7080 — native high-performance API
- REST/JSON on port 7081 — HTTP/JSON transcoding via embedded structured-proxy
Query Parameters (REST)
Named parameters are passed in the parameters map. Each value is a JSON object with a single key matching the PropertyValue proto field name:
{
"query": "MATCH (n:Concept {name: $name}) RETURN n",
"parameters": {
"name": { "stringValue": "machine learning" },
"limit": { "intValue": "10" },
"threshold": { "floatValue": 0.4 },
"active": { "boolValue": true },
"question_vector": { "vectorValue": { "values": [0.1, 0.2, 0.3] } },
"tags": { "listValue": { "values": [{"stringValue": "ml"}, {"stringValue": "ai"}] } }
}
}Available parameter types:
| JSON key | Proto field | Example |
|---|---|---|
stringValue | string | { "stringValue": "alice" } |
intValue | int64 | { "intValue": "42" } |
floatValue | double | { "floatValue": 0.95 } |
boolValue | bool | { "boolValue": true } |
vectorValue | Vector | { "vectorValue": { "values": [0.1, 0.2] } } |
listValue | PropertyList | { "listValue": { "values": [...] } } |
bytesValue | bytes | { "bytesValue": "<base64>" } |
Vector parameters: use
vectorValue, notlistValue.vectorValuemaps to the dedicatedVectorproto type and enables vector index pushdown in the query planner.
Methods
ExecuteCypher
Execute an OpenCypher query and return results.
HTTP: POST /v1/query/cypher
Request: ExecuteCypherRequest
| Field | Type | Description |
|---|---|---|
query | string | OpenCypher query string. |
parameters | map<string, PropertyValue> | Named query parameters bound at execution time. |
read_preference | ReadPreference | Which cluster node may serve this read. UNSPECIFIED takes the server's configured default, PRIMARY (leader-only reads) unless the operator set another. Use SECONDARY_PREFERRED for read scale-out in 3-node CE cluster. A value the server does not know is rejected with INVALID_ARGUMENT. |
read_concern | ReadConcern | Data consistency guarantee for this read. An omitted message or an UNSPECIFIED level takes the server's configured default, LOCAL (whatever this node has applied) unless the operator set another. Use MAJORITY for reads that must not see rolled-back data. Use LINEARIZABLE for strictest freshness (leader only, adds ~1 RTT). A level the server does not know is rejected with INVALID_ARGUMENT. |
write_concern | WriteConcern | Durability guarantee for write statements (CREATE / MERGE / SET / DELETE). Omitted takes the server's configured default; that is MAJORITY with the write journaled on each counted member unless the operator set another. Present with w unset means MAJORITY. Ask for a weaker concern explicitly, per request (acks: 1, acks: 0, journal: MEMORY), for writes that may be lost with their leader. Causal sessions (read_concern.after_index > 0) require write_concern MAJORITY. The server rejects writes with lower durability in causal sessions because a non-majority write may never be replicated: if the leader crashes before drain, the returned applied_index becomes a dangling causal dependency that can never be satisfied by a follower read. Read-only queries ignore this field. |
transaction_id | uint64 | Interactive transaction handle (from BeginTransaction). When non-zero, this statement runs inside that transaction: it reads the transaction's pinned snapshot and its writes buffer until CommitTransaction. When zero (omitted), the statement auto-commits on its own (the default). |
vector_consistency | VectorConsistency | Vector consistency of this statement, below a vector_consistency hint in its query. UNSPECIFIED leaves it to the server: the mode the query's read consistency implies. A node passing a session's statement to the leader carries the session's setting here. |
vector_build_wait_ms | uint32 | How long this statement waits for a vector index still being built, in milliseconds, below a vector_build_wait hint in its query. Absent takes the server's vector_build_wait_ms; 0 refuses a building index at once. |
query_memory_limit_mb | uint32 | Memory limit of this statement, in MiB: what its operators, access paths and buffered results may hold at once. Absent takes the server's query_memory_limit_mb. Zero or a value past the administrative ceiling (4096 MiB) is rejected with INVALID_ARGUMENT. A statement that needs more fails with RESOURCE_EXHAUSTED, reason EXCEEDS_MEMORY_BUDGET, and returns no partial result. A node passing a session's statement to the leader carries the session's setting here. The statement's deadline is the call's gRPC deadline. |
Response: ExecuteCypherResponse
| Field | Type | Description |
|---|---|---|
columns | string[] | — |
rows | Row[] | — |
stats | QueryStats | — |
ExplainCypher
Explain an OpenCypher query plan without executing.
HTTP: POST /v1/query/cypher/explain
Request: ExplainCypherRequest
| Field | Type | Description |
|---|---|---|
query | string | — |
parameters | map<string, PropertyValue> | — |
Response: ExplainCypherResponse
| Field | Type | Description |
|---|---|---|
plan | QueryPlan | — |
BeginTransaction
Begin an interactive multi-statement transaction. Returns a transaction_id; pass it on ExecuteCypherRequest for each statement, then CommitTransaction or RollbackTransaction. All statements read the same pinned snapshot (repeatable read) and writes commit atomically at commit.
HTTP: POST /v1/query/transaction/begin
Request: BeginTransactionRequest
Empty request (no fields).
Response: BeginTransactionResponse
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | Handle for subsequent ExecuteCypher / CommitTransaction / RollbackTransaction calls. Always non-zero. |
CommitTransaction
Commit an interactive transaction: validate the read-set, then persist every buffered statement's writes in a single proposal.
HTTP: POST /v1/query/transaction/commit
Request: CommitTransactionRequest
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | — |
expect | ExpectedNodeVersion[] | Commit only while these nodes are still at these versions. An empty list is the ordinary unconditional commit. The condition is checked when the transaction commits, against the state at that moment, so it protects the window between the read the caller built on and the write it is making. A mismatch refuses the whole transaction with ABORTED and reason REVISION_MISMATCH, carrying expected_version and current_version in the error metadata: the caller decides what to do next from those rather than reading the node again and racing a second time. |
Response: CommitTransactionResponse
| Field | Type | Description |
|---|---|---|
applied_index | uint64 | Raft log index the commit was applied at on the serving node — the causal token clients pass as after_index on later reads. 0 in embedded mode. |
commit_ts | uint64 | HLC commit timestamp (microseconds since the Unix epoch) every mutation of the transaction was applied at. Server-assigned. Commit timestamps are the storage sequence numbers, so this value is the exact snapshot anchor for the write: AS OF TIMESTAMP <commit_ts> (or ReadConcern.at_timestamp) sees this transaction and nothing committed later, and a change-stream consumer that has processed it resumes from commit_ts + 1. Present in every mode; a read-only transaction reports its pinned read timestamp. |
RollbackTransaction
Roll back an interactive transaction: discard all buffered writes.
HTTP: POST /v1/query/transaction/rollback
Request: RollbackTransactionRequest
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | — |
Response: RollbackTransactionResponse
Empty response (no fields).
Types
BeginTransactionRequest
No fields.
BeginTransactionResponse
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | Handle for subsequent ExecuteCypher / CommitTransaction / RollbackTransaction calls. Always non-zero. |
CommitTransactionRequest
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | — |
expect | ExpectedNodeVersion[] | Commit only while these nodes are still at these versions. An empty list is the ordinary unconditional commit. The condition is checked when the transaction commits, against the state at that moment, so it protects the window between the read the caller built on and the write it is making. A mismatch refuses the whole transaction with ABORTED and reason REVISION_MISMATCH, carrying expected_version and current_version in the error metadata: the caller decides what to do next from those rather than reading the node again and racing a second time. |
CommitTransactionResponse
| Field | Type | Description |
|---|---|---|
applied_index | uint64 | Raft log index the commit was applied at on the serving node — the causal token clients pass as after_index on later reads. 0 in embedded mode. |
commit_ts | uint64 | HLC commit timestamp (microseconds since the Unix epoch) every mutation of the transaction was applied at. Server-assigned. Commit timestamps are the storage sequence numbers, so this value is the exact snapshot anchor for the write: AS OF TIMESTAMP <commit_ts> (or ReadConcern.at_timestamp) sees this transaction and nothing committed later, and a change-stream consumer that has processed it resumes from commit_ts + 1. Present in every mode; a read-only transaction reports its pinned read timestamp. |
ExecuteCypherRequest
| Field | Type | Description |
|---|---|---|
query | string | OpenCypher query string. |
parameters | map<string, PropertyValue> | Named query parameters bound at execution time. |
read_preference | ReadPreference | Which cluster node may serve this read. UNSPECIFIED takes the server's configured default, PRIMARY (leader-only reads) unless the operator set another. Use SECONDARY_PREFERRED for read scale-out in 3-node CE cluster. A value the server does not know is rejected with INVALID_ARGUMENT. |
read_concern | ReadConcern | Data consistency guarantee for this read. An omitted message or an UNSPECIFIED level takes the server's configured default, LOCAL (whatever this node has applied) unless the operator set another. Use MAJORITY for reads that must not see rolled-back data. Use LINEARIZABLE for strictest freshness (leader only, adds ~1 RTT). A level the server does not know is rejected with INVALID_ARGUMENT. |
write_concern | WriteConcern | Durability guarantee for write statements (CREATE / MERGE / SET / DELETE). Omitted takes the server's configured default; that is MAJORITY with the write journaled on each counted member unless the operator set another. Present with w unset means MAJORITY. Ask for a weaker concern explicitly, per request (acks: 1, acks: 0, journal: MEMORY), for writes that may be lost with their leader. Causal sessions (read_concern.after_index > 0) require write_concern MAJORITY. The server rejects writes with lower durability in causal sessions because a non-majority write may never be replicated: if the leader crashes before drain, the returned applied_index becomes a dangling causal dependency that can never be satisfied by a follower read. Read-only queries ignore this field. |
transaction_id | uint64 | Interactive transaction handle (from BeginTransaction). When non-zero, this statement runs inside that transaction: it reads the transaction's pinned snapshot and its writes buffer until CommitTransaction. When zero (omitted), the statement auto-commits on its own (the default). |
vector_consistency | VectorConsistency | Vector consistency of this statement, below a vector_consistency hint in its query. UNSPECIFIED leaves it to the server: the mode the query's read consistency implies. A node passing a session's statement to the leader carries the session's setting here. |
vector_build_wait_ms | uint32 | How long this statement waits for a vector index still being built, in milliseconds, below a vector_build_wait hint in its query. Absent takes the server's vector_build_wait_ms; 0 refuses a building index at once. |
query_memory_limit_mb | uint32 | Memory limit of this statement, in MiB: what its operators, access paths and buffered results may hold at once. Absent takes the server's query_memory_limit_mb. Zero or a value past the administrative ceiling (4096 MiB) is rejected with INVALID_ARGUMENT. A statement that needs more fails with RESOURCE_EXHAUSTED, reason EXCEEDS_MEMORY_BUDGET, and returns no partial result. A node passing a session's statement to the leader carries the session's setting here. The statement's deadline is the call's gRPC deadline. |
ExecuteCypherResponse
| Field | Type | Description |
|---|---|---|
columns | string[] | — |
rows | Row[] | — |
stats | QueryStats | — |
ExpectedNodeVersion
A node and the version the caller believes it is at.
| Field | Type | Description |
|---|---|---|
node_id | uint64 | — |
version | uint64 | The version read earlier (Node.version). Unset requires the node NOT to exist, which is the create-if-absent form of the same condition; it is optional rather than a zero sentinel because zero is not a version a node can have, and a field that means "absent" must be able to say so. |
ExplainCypherRequest
| Field | Type | Description |
|---|---|---|
query | string | — |
parameters | map<string, PropertyValue> | — |
ExplainCypherResponse
| Field | Type | Description |
|---|---|---|
plan | QueryPlan | — |
MultiVector
An ordered set of equal-width vectors representing one item, as produced by late-interaction retrieval models (ColBERT v2, MaxSim) where a document is several token-level embeddings rather than one pooled vector.
Every row carries the same number of dimensions; the sender enforces that invariant, so a receiver may read rows[0] for the width.
| Field | Type | Description |
|---|---|---|
rows | Vector[] | — |
Path
A graph path: the alternating node/relationship sequence produced by shortestPath(...) and by a variable-length MATCH p = (a)-[*]->(b).
rels has exactly one fewer entry than nodes on a non-empty path, and the n-th hop connects nodes[n] to nodes[n+1]. An empty path (a single node, zero hops) carries one node and no relationships.
| Field | Type | Description |
|---|---|---|
nodes | uint64[] | Node ids along the path, start to end. |
rels | PathRel[] | Relationship hops, in the same order. |
PathRel
One relationship hop inside a Path: its type and endpoint node ids. Relationship properties are not carried; fetch them by endpoint pair when they are needed.
| Field | Type | Description |
|---|---|---|
edge_type | string | — |
source | uint64 | — |
target | uint64 | — |
QueryPlan
| Field | Type | Description |
|---|---|---|
operator | string | — |
details | map<string, string> | — |
children | QueryPlan[] | — |
estimated_rows | double | — |
QueryStats
| Field | Type | Description |
|---|---|---|
nodes_created | int64 | — |
nodes_deleted | int64 | — |
edges_created | int64 | — |
edges_deleted | int64 | — |
properties_set | int64 | — |
execution_time_ms | int64 | — |
applied_index | uint64 | Raft log index applied on the serving node at query time. Clients use this as after_index in subsequent causal reads. 0 means the node is not part of a Raft cluster (embedded mode). |
served_by_leader | bool | True when the read was served by the Raft leader. False for follower reads (read_preference = SECONDARY or NEAREST). |
commit_ts | uint64 | The HLC timestamp this statement's writes landed at, for a statement that committed on its own. Zero for a read, and for a statement inside an interactive transaction, whose timestamp belongs to the commit that ends it (CommitTransactionResponse.commit_ts). This is the version of what the statement wrote: the same number Node.version reports and CommitTransactionRequest.expect is stated against. A client that writes and then means to write again conditionally already holds what to state, with no read in between. |
read_as_of_ts | uint64 | Set by a member that does not run the version its group runs and so is read-only: the commit timestamp of the last entry it applied, which this read reflects and nothing after. Zero for a read served by a member that runs its group's version. A read that must be current is refused by such a member instead (FAILED_PRECONDITION, reason MEMBER_READ_ONLY). |
ReadConcern
Read concern configuration.
| Field | Type | Description |
|---|---|---|
level | ReadConcernLevel | Consistency level for this read. UNSPECIFIED defaults to LOCAL. |
after_index | uint64 | Causal fence: wait until the serving node has applied log entries up to at least this Raft log index before executing the read. Set to the QueryStats.applied_index value from a prior write response to guarantee read-your-writes: the read is guaranteed to observe all mutations up to and including that write. 0 = no fence (default). Only valid with level = MAJORITY or SNAPSHOT; returns FAILED_PRECONDITION if level = LOCAL or LINEARIZABLE. Has no effect in standalone (non-Raft) mode — all writes are immediately visible. The returned applied_index will always be 0 in standalone mode, so clients should not set after_index unless operating in cluster mode. |
at_timestamp | uint64 | Snapshot pin: read the database as of this HLC timestamp (microseconds since Unix epoch, leader-assigned). Only valid with level = SNAPSHOT. Setting this with any other level returns FAILED_PRECONDITION. 0 = no pin (latest snapshot of the chosen level applies). Typical use: time-travel reads ("what did this query return at 2026-05-15 12:00:00?"). The timestamp must be within the MVCC retention window — older snapshots are GC'd. Reads beyond retention return UNAVAILABLE. Distinct from after_index: after_index is a fence (wait until at least this index is applied), at_timestamp is a pin (read exactly this version, no waiting). |
RollbackTransactionRequest
| Field | Type | Description |
|---|---|---|
transaction_id | uint64 | — |
RollbackTransactionResponse
No fields.
Row
| Field | Type | Description |
|---|---|---|
values | PropertyValue[] | — |
Timestamp
An instant on the time axis of a TIMESTAMP property.
| Field | Type | Description |
|---|---|---|
unix_micros | int64 | Microseconds since the Unix epoch (1970-01-01T00:00:00Z), signed: an instant before the epoch is negative. Microseconds are the database's own resolution, so the value round-trips exactly; a client converts it to its native type (a nanosecond type reaches it losslessly). |
WriteConcern
Write concern configuration for a write statement or a session default.
Two independent axes, as in MongoDB: w (how many members acknowledge) and journal (what state each of them holds the write in). w is either a count of members or a named mode; the two never share a number space, so acks: 3 is three members in a group of any size and can never be confused with a mode. Leaving w unset selects the default, MAJORITY; asking for fire-and-forget is always explicit (acks: 0). Neither axis is ever silently changed to satisfy the other: a combination the server cannot honour is rejected with INVALID_ARGUMENT.
| Field | Type | Description |
|---|---|---|
journal | Journal | The state each counted member holds the write in. Omitted = JOURNAL. CACHE and MEMORY are accepted only with acks: 0 or acks: 1: a volatile state cannot be confirmed across members, so combining them with acks above 1 or with MAJORITY is rejected with INVALID_ARGUMENT. |
timeout_ms | uint32 | Time in milliseconds to wait for w to be satisfied; 0 = no timeout. On timeout the call fails, but the write is NOT rolled back: it may still commit afterwards. |
acks | uint32 | Number of members, the leader included, that must hold the write in the journal state before the caller is answered. 0 = fire-and-forget: the write still goes through the leader and the log, the caller is answered at once and is not told whether it committed. 1 = the leader alone (rollback possible if the leader fails before replication). N = N members. A value above the group's member count is rejected with INVALID_ARGUMENT. |
mode | WriteConcernMode | A named rule instead of a count. See WriteConcernMode. |
Enums
Journal
The state each acknowledging member must hold the write in before it counts towards w. Independent of w: w says how many members, journal says how durably each of them holds the write.
A write concern decides when the caller is answered, never whether the write is replicated: every write enters the group's log through the leader and is applied on every member. CACHE and MEMORY answer before the write is in the log and keep it in a volatile overlay until the drain proposes it; a leader crash before the drain loses every write still in that overlay. Use them for telemetry, hot counters and session state only, never for source-of-truth data.
| Value | Number | Description |
|---|---|---|
JOURNAL_UNSPECIFIED | 0 | Same as JOURNAL: the default when the field is omitted. |
JOURNAL_JOURNAL | 1 | The write is fsynced to the member's journal (the Raft log) before it is counted. Survives process crash and power failure. |
JOURNAL_CACHE | 2 | The write is in the member's RAM + NVMe overlay (~100µs) before it is counted. Survives a process crash, not a power failure before the drain. |
JOURNAL_MEMORY | 3 | The write is in the member's RAM-only overlay (~1µs) before it is counted. Visible at once to local readers that accept volatile data; lost on process crash before the drain. |
ReadConcernLevel
Read concern levels.
| Value | Number | Description |
|---|---|---|
READ_CONCERN_LEVEL_UNSPECIFIED | 0 | — |
READ_CONCERN_LEVEL_LOCAL | 1 | Read from local replica (may be stale). |
READ_CONCERN_LEVEL_MAJORITY | 2 | Read data committed by majority. |
READ_CONCERN_LEVEL_LINEARIZABLE | 3 | Linearizable read (strongest guarantee). |
READ_CONCERN_LEVEL_SNAPSHOT | 4 | Read from a consistent MVCC snapshot. |
ReadPreference
Read preference for routing read operations.
| Value | Number | Description |
|---|---|---|
READ_PREFERENCE_UNSPECIFIED | 0 | — |
READ_PREFERENCE_PRIMARY | 1 | — |
READ_PREFERENCE_PRIMARY_PREFERRED | 2 | — |
READ_PREFERENCE_SECONDARY | 3 | — |
READ_PREFERENCE_SECONDARY_PREFERRED | 4 | — |
READ_PREFERENCE_NEAREST | 5 | — |
VectorConsistency
How a vector search treats the read's snapshot: the same modes as the query hint vector_consistency('...') and the session command SET vector_consistency = '...'. A hint in the query wins over this setting.
| Value | Number | Description |
|---|---|---|
VECTOR_CONSISTENCY_UNSPECIFIED | 0 | Unset: left to the next level down, the session's setting and then the mode the query's read consistency implies. |
VECTOR_CONSISTENCY_CURRENT | 1 | The index's current state with no visibility filter: fastest, best recall, may include writes newer than the snapshot. |
VECTOR_CONSISTENCY_SNAPSHOT | 2 | Index candidates filtered by visibility at the snapshot. |
VECTOR_CONSISTENCY_EXACT | 3 | Every vector of the label at the snapshot, without the index: exact, and its cost grows with the label. |
WriteConcernMode
Named write concern modes: rules for w that are not a fixed count of members.
| Value | Number | Description |
|---|---|---|
WRITE_CONCERN_MODE_UNSPECIFIED | 0 | Not a valid choice on the wire: a WriteConcern whose w is unset means the default, MAJORITY. Set mode explicitly to one of the values below. |
WRITE_CONCERN_MODE_MAJORITY | 1 | Acknowledged once a majority of the group's members (the leader included) holds the write in the state named by journal. Survives the loss of a minority. The default. |
