Skip to content

INSERT

INSERT creates nodes and edges in the current open graph. It runs through Session::run(...).await or the CLI; the read-only query API rejects writes.

MATCH (alice:Person {name: 'Alice'})
INSERT (alice)-[:Knows]->(dana:Person & Admin {name: 'Dana', age: 28})
RETURN dana.name AS name;

A bound node appears as a bare reference, such as (alice). New nodes can have labels and properties; edge variables must be new. RETURN * projects every variable declared by the insert. An anonymous pattern such as (:Seen) declares none. A new destination may read the edge that connects it, as in (a)-[e:Knows {since: 2020}]->(b {met: e.since}). The edge may still read both endpoints. Properties of the destination that do not mention the edge are visible to that edge.

INSERT (extra:Person {name: 'Eve'})
RETURN *;

Incoming/outgoing edges, undirected connections, self-loops and parallel edges are supported.

Creation requires concrete labels: names joined by & are accepted, while !, | and % are rejected. Labels are case-sensitive, so a bare conjunction such as (A & a) stores both spellings, the same as (:A & a). Every input row creates its new elements; repeated input rows can therefore insert duplicates. Empty input inserts nothing. A null optional endpoint is an invalid query, and that statement inserts nothing.

A property value that is null on every inserted row does not create that property. 1 + NULL, NULLIF and other null expressions leave it unset, just as a literal NULL does. One non-null value keeps the column and its type.

A complete statement publishes atomically after its result pipeline succeeds. A later expression error rolls back that statement’s inserts. Multiple semicolon-separated statements auto-commit independently unless enclosed in an explicit transaction.

Arithmetic and concatenation in property values use each source fragment’s stored type. Incompatible fragments yield null before enclosing expressions such as COALESCE apply their fallback.