Omnigraph
Mutations

Insert

Add new nodes and edges to the graph.

The insert operation adds new nodes and edges to the graph. Inserts are validated against the schema at commit time: every required property must be present, types must match, and constraint annotations are enforced.

Inserting nodes

Use insert TypeName { ... } inside a named query to add a node:

query add_person($name: String, $age: I32) {
    insert Person { name: $name, age: $age }
}

Run it from the CLI:

omnigraph change ./my-graph \
    --query mutations.gq \
    --name add_person \
    --params '{"name": "Alice", "age": 30}'

Or via the HTTP API:

curl -X POST http://localhost:4000/change \
    -H "Content-Type: application/json" \
    -d '{
        "uri": "./my-graph",
        "query": "mutations.gq",
        "name": "add_person",
        "params": {"name": "Alice", "age": 30}
    }'

Nullable properties

Properties marked with ? in the schema can be omitted from the insert. Omitted nullable properties default to null:

node Person {
    name: String @key
    age:  I32?
    bio:  String?
}
query add_person($name: String) {
    insert Person { name: $name }
}

This inserts a Person with age and bio set to null.

Inserting edges

Edges connect two existing nodes. You reference the source and destination by their @key values:

query add_edge($person: String, $company: String) {
    insert WorksAt { src: $person, dst: $company }
}
omnigraph change ./my-graph \
    --query mutations.gq \
    --name add_edge \
    --params '{"person": "Alice", "company": "Acme"}'

If the edge type has properties, include them in the insert:

query add_knows($a: String, $b: String, $since: Date) {
    insert Knows { src: $a, dst: $b, since: $since }
}

Both the source and destination nodes must already exist. If either is missing, the insert fails with a referential integrity error.

Upsert behavior for @key types

When you insert a node whose type has a @key property, and a node with that key value already exists, Omnigraph performs an upsert: the existing node is updated with the new property values instead of creating a duplicate.

node Person {
    name: String @key
    age:  I32?
}
query upsert_person($name: String, $age: I32) {
    insert Person { name: $name, age: $age }
}

If a Person with name = "Alice" already exists, this updates her age rather than inserting a second row.

Constraint validation

Inserts are checked against every constraint declared in the schema:

ConstraintBehavior on insert
@keyUpserts if a matching key already exists
@uniqueRejects the insert if a duplicate value exists
@rangeRejects the insert if the value is outside the declared range
@checkRejects the insert if the check expression evaluates to false
Required propertiesRejects the insert if a non-nullable property is missing

If any constraint fails, the entire transaction is rolled back and no data is written.

Bulk inserts with JSONL

For loading large volumes of data, use the load subcommand with a JSONL file instead of individual insert mutations:

omnigraph load ./my-graph --data data.jsonl

See the Quick Start for the JSONL format.

Blob properties

Node types with Blob properties accept two value formats in inserts.

Base64-encoded inline data:

query add_photo($slug: String) {
    insert Photo {
        slug: $slug,
        image: "base64:iVBORw0KGgo...",
    }
}

URI reference (S3 or local path):

query add_photo_from_s3($slug: String) {
    insert Photo {
        slug: $slug,
        image: "s3://my-bucket/photos/sunset.jpg",
    }
}

Blob properties appear as null in normal query projections. To read blob bytes, use the dedicated blob read API rather than a standard return projection.

On this page