Cypher Writes And Schema
Submit Cypher writes through the ExecuteCypher gRPC method with write authorization. The read-only Direct Query and semantic interfaces reject mutations; use the gRPC connection workflow for these examples.
The general planner executes supported mutations through governed operators backed by the graph write service.
Those operators are disabled by default; the legacy fast paths described below have a separate execution boundary.
Enable Governed Writes
Set SHRIKEDB_CYPHER_WRITE_MODE=canary or full before starting the server to admit supported writes through the governed executor.
off is the default. The mode names do not provide automatic traffic sampling or establish broader language support.
For a local test server, set the mode in the same shell before starting it:
export SHRIKEDB_CYPHER_WRITE_MODE=full
shrikedb --config "$HOME/.shrikedb/guide.yaml" --no-startup-ui
For a managed service, add the variable to the service environment and restart normally. This enables the supported general write operators; user permissions still control who may write.
|
|
Create And Update
These examples modify the selected database; use a disposable database when trying them.
CREATE (p:Person {id: 'guide-alice', name: 'Alice'})
RETURN p
MATCH (p:Person {id: 'guide-alice'})
SET p.active = true
RETURN p
MATCH (p:Person {id: 'guide-alice'})
REMOVE p.active
RETURN p
Directed relationship creation is supported between bound endpoints:
MATCH (a:Person {id: 'guide-alice'}), (b:Person {id: 'guide-bob'})
CREATE (a)-[:KNOWS]->(b)
RETURN a, b
Both endpoint nodes must exist for this example. Create Bob with the same single-node CREATE pattern used for Alice, using id: 'guide-bob' and name: 'Bob', before creating the relationship.
Use one label per CREATE node: the current writer persists only the first supplied label.
Do not rely on CREATE (n:Person:Employee) to preserve both memberships.
The bulk graph write API can load multiple label payloads for a node; verify memberships after loading and recovery.
Deterministic MERGE
Supported node merges use one literal label and a deterministic property map:
MERGE (p:Person {id: 'guide-alice'})
ON CREATE SET p.created = true
ON MATCH SET p.seen = true
RETURN p
Directed single-hop relationship merges support bound endpoints or supported deterministic endpoint descriptors:
MATCH (a:Person {id: 'guide-alice'}), (b:Person {id: 'guide-bob'})
MERGE (a)-[:KNOWS]->(b)
RETURN a, b
Ambiguous existing node matches are errors; the executor does not choose an arbitrary node.
When a uniqueness constraint covers the MERGE key, the storage write guard prevents concurrent requests from publishing the same value.
Multi-hop or undirected MERGE, variable-length relationships, relationship property maps, multi-label node merges and branch updates targeting relationship variables remain unsupported.
Delete
DELETE n accepts a bound node with no incident relationships.
DETACH DELETE n also removes its incident relationships from visible graph state through durable tombstones.
MATCH (p:Person {id: 'guide-alice'})
DETACH DELETE p
Relationship-variable deletion (DELETE r), label removal (REMOVE n:Label), dynamic labels/types and write subqueries are outside the supported write scope.
Write results can include cypher_write_status, cypher_write_subject, action/byte counts, node/edge counts and a receipt hash for inspection.
Persistent schema declarations
The parser and executor support database-wide CREATE INDEX, DROP INDEX, SHOW INDEXES, CREATE CONSTRAINT, DROP CONSTRAINT, and SHOW CONSTRAINTS commands.
Schema mutations require the separate SHRIKEDB_CYPHER_SCHEMA_MODE=canary|full setting; its default is off.
SHOW INDEXES
SHOW CONSTRAINTS
Schema definitions are durable and owned by the database directory. They are visible to every authorized caller and apply to node writes from every authenticated principal, so changing credentials cannot bypass an invariant. Acknowledged creates and drops survive process restarts.
CREATE INDEX builds an exact label-and-property index from the current published graph snapshot before it returns.
The index is maintained with subsequent node writes and rebuilt from durable graph data during recovery.
SHOW INDEXES returns state = 'ONLINE' after construction succeeds and includes entries and distinct_values so an operator can inspect the populated index.
CREATE CONSTRAINT validates every existing node with the selected label before publishing the definition.
A uniqueness constraint rejects duplicate property values; nodes without that property remain valid unless an existence constraint also applies.
An existence constraint requires every node with the selected label to carry the named property.
The write guard evaluates the final node state, so it covers creates, property updates, property removal, deletion, batch writes, governed Cypher writes, and server fast paths that use the graph write service.
An invalid batch is rejected before any node in that batch is inserted.
Concurrent writes are serialized through constraint validation and durable publication, preventing two acknowledged writes from claiming the same constrained value.
Constraints apply to property-graph node records. RDF triples, KV entries, and vectors retain their own data models and indexes, so enabling a Cypher constraint does not change SPARQL, KV, or vector semantics.
With schema mode enabled, these commands declare, inspect, and remove a sample index. Submit each through ExecuteCypher:
CREATE INDEX person_id FOR (n:Person) ON (n.id)
SHOW INDEXES
DROP INDEX person_id
A uniqueness constraint and a required-property constraint can be combined:
CREATE CONSTRAINT person_unique
FOR (n:Person) REQUIRE n.id IS UNIQUE
CREATE CONSTRAINT person_id_required
FOR (n:Person) REQUIRE n.id IS NOT NULL
If existing data violates either rule, creation returns an error and leaves the active schema unchanged.
Storage, Recovery And Upgrades
The database data directory contains cypher_schema_catalog.json, a versioned and checksummed catalog, and cypher_schema_catalog.lock, its coordination file.
Successful DDL syncs a temporary file, atomically replaces the catalog and syncs the parent directory before returning its receipt.
Catalog commands serialize through a filesystem lock with a five-second acquisition budget.
The database also coordinates DDL with constrained node writes, so an acknowledged constraint cannot become active between validation and durable publication of a conflicting write.
Ordinary read queries do not take either lock.
The catalog is limited to 16 MiB. Use a local filesystem with the locking and durability behavior required by your deployment.
DDL commits independently of graph transactions, as before; graph rollback does not undo catalog changes.
Deploy the same catalog with each database replica and perform schema changes through the cluster’s controlled rollout process before admitting writes on a promoted replica.
Schema definitions describe the current database and are not historical schema views for older graph snapshots.
If no catalog exists, SHOW returns no declarations and the first admitted mutation creates the catalog.
The former in-memory catalog cannot be recovered after its process has stopped; capture SHOW INDEXES / SHOW CONSTRAINTS and reissue the corresponding DDL when upgrading a process that still holds declarations.
An older binary cannot read this new catalog. It can still use existing graph data, but its in-memory DDL changes will not update the durable file; avoid DDL during such a rollback.
Include the catalog in a stopped-database backup or a coordinated filesystem snapshot with the database data.
Do not replace or remove the lock file while any catalog user is running.
Corrupt files, unknown format versions and I/O failures produce explicit schema errors; they are never silently replaced by an empty catalog.
Unrelated Cypher, SPARQL and multimodal reads remain available if catalog inspection fails.
A failure after replacement but before directory sync reports an uncertain outcome; inspect and retry the same DDL after resolving the I/O error.
For query-plan inspection, see EXPLAIN and PROFILE.