UltipaDocs
Products
Solutions
Resources
Company
Start Free Trial
UltipaDocs
Start Free Trial
  • Introduction
  • GQL vs Other Languages
    • Overview
    • Node and Edge Patterns
    • Path Patterns
    • Quantified Paths
    • Questioned Paths
    • Shortest Paths
    • Cheapest Paths
    • K-Hop Traversal
    • Graph Patterns
    • Overview
    • Open Graphs
    • Closed Graphs
    • Graph Types
    • Constraints
    • Projections
    • Storage Maintenance
    • Node and Edge IDs
    • INSERT
    • INSERT OVERWRITE
    • UPSERT
    • MERGE
    • SET
    • REMOVE
    • DELETE
    • FOREACH
    • LOAD CSV
    • Query Composition
    • Result Table and Visualization
    • MATCH
    • OPTIONAL MATCH
    • FILTER
    • LET
    • FOR
    • ORDER BY
    • LIMIT
    • SKIP
    • CALL
    • RETURN
    • Composite Query
    • NEXT
    • All Functions
    • Element Functions
    • Path Functions
    • Aggregate Functions
    • Mathematical Functions
    • Trigonometric Functions
    • String Functions
    • List Functions
    • Datetime Functions
    • Spatial Functions
    • Null Functions
    • Utility Functions
    • Type Conversion Functions
    • Table Functions
  • Operators
  • Predicates
    • CASE
    • LET Value Expression
    • Value Query Expression
    • List Expressions
    • Current Values
    • Index
    • Full-text Index
    • Vector Index
  • Transactions
  • Triggers
  • Query Management
  • Execution Plan
    • Variables
    • Values and Types
    • Comments
    • Reserved Words
    • Naming Conventions
    • Syntactic Notation
  • GQL Conformance
  1. Docs
  2. /
  3. ISO GQL
  4. /
  5. Data Manipulation

INSERT

Overview

The INSERT statement allows you to add new nodes and edges into the graph using node and edge patterns.

Syntax
<insert statement> ::=
  "INSERT" <insert path pattern> [ { "," <insert path pattern> } ... ]

<insert path pattern> ::=
  <insert node pattern> [ { <insert edge pattern> <insert node pattern> } ... ]

<insert node pattern> ::=
  "(" [ <node variable declaration> ] [ <label expression> ] [ <property specification> ] ")"

<insert edge pattern> ::=
    "-" [ <edge variable declaration> ] [ <label expression> ] [ <property specification> ] "->"
  | "<-" [ <edge variable declaration> ] [ <label expression> ] [ <property specification> ] "-"

Details

  • <insert path pattern> supports single node pattern or simple concatenation of node and edge patterns.
  • <insert path pattern> does not support WHERE clause or undirected edges.

Ultipa supports both closed graphs and open graphs. Their data insertion syntax is similar, but with important differences in requirements.

Open Graphs

For an open graph, you can directly insert nodes and edges, and the labels and properties are created on the fly.

  • Labels: You may assign zero, one, or multiple labels to a node or edge.
  • Properties: Each node or edge has its own set of properties. Any property name is accepted — there is no schema validation. The property value type is inferred from the literal value at insertion time (e.g., 30 is stored as INT, "hello" as STRING, [1,2] as LIST). Unlike closed graphs where types are explicitly defined (e.g., UINT32 vs INT64), open graphs have no fine-grained type control.

Learn more about open graphs →

Closed Graphs

For a closed graph, any node or edge inserted must conform to its defined node or edge type:

  • Labels: The insert label set must exactly match the full label set of a defined type. For example, if node type User has labels [User, Employee], you must insert with :User&Employee. Each edge only supports one label.
  • Properties: Only properties defined in the type are allowed. Each property has an explicitly defined value type (e.g., STRING, UINT32, FLOAT), and inserted values are validated against these types. Properties not provided in the insert default to null, unless a NOT NULL constraint is defined. Inserting an undefined property name results in an error.

Learn more about closed graphs →

Inserting Nodes

Insert a single User node:

GQL
INSERT (:User {name: "claire", gender: "female"})

Insert multiple nodes and return them:

GQL
INSERT (n1:User&Employee {_id: "U2", name: "Quasar92"}),
       (n2:Club {_id: "C1"}),
       (n3:Club)
RETURN n1, n2, n3
NOTE

Node _id on insert: You can assign a custom _id on nodes at insert time; if _id is omitted, the node receives a system-generated UUID v4 _id value.

Inserting Edges

Insert an edge between existing nodes, first retrieve the nodes using MATCH:

GQL
MATCH (n1:User {name: 'claire'}), (n2:Club {_id: 'C1'})
INSERT (n1)-[e:Joins {fee: 1200}]->(n2)
RETURN e

Insert a Joins edge from an existing User node to a new Club node:

GQL
MATCH (user:User {name: 'Quasar92'})
INSERT (user)-[:Joins]->(:Club {_id: "C2"})
NOTE

Edge _id on insert: edge _id is enabled on newly created graphs by default, you can assign a custom _id on edges at insert time; if _id is omitted, the edge receives a system-generated UUID v4 _id value. On graphs created with edge _id disabled (or toggled off later), each edge receives a system-assigned _id value in the e:<N> form, and supplying _id in the edge property specification is rejected. See Node and Edge IDs.

Inserting Paths

Insert two User nodes and a Follows edge between them:

GQL
INSERT (:User {name: 'rowlock'})-[:Follows {since: date('2024-01-05')}]->(:User {name: 'Brainy', gender: 'male'})

Insert the 4 nodes and 3 edges shown below, consider it as two paths intersecting at the Club node:

GQL
INSERT (:User {name: 'waveBliss'})-[:Joins]->(c:Club {_id: 'C3'}),
       (:User {name: 'bella'})-[:Joins]->(c)<-[:Joins]-(:User {name: 'Roose'})

Alternatively, you can insert each node and edge individually:

GQL
INSERT (waveBliss:User {name: 'waveBliss'}),
       (bella:User {name: 'bella'}),
       (Roose:User {name: 'Roose'}),
       (C3:Club {_id: 'C3'}),
       (waveBliss)-[:Joins]->(C3),
       (bella)-[:Joins]->(C3),
       (Roose)-[:Joins]->(C3)

Property Value Examples

Below are examples of property values for different types. See Property Value Types for the complete list.

GQL
INSERT (:Person {
  // Numeric
  memberLevel: 2, score: 60.3,
  
  // Textual
  name: "John Doe", bio: 'A short bio',

  // Temporal Instance
  birthday: date('2000-01-15'),
  registered: local_datetime('2025-01-01 12:20:02'),
  lastLogin: 1762338059,
  meetingTime: time('14:30:00'),
  zonedAt: zoned_datetime('2025-01-01T12:20:02+08:00'),

  // Temporal Duration
  membership: duration('P2Y5M'),
  
  // Boolean
  isBlocked: FALSE,

  // Spatial
  location: point(125.6, 22.3),
  position: point3d(10, 3.4, 6.2),
  
  // Record
  bodyInfo: {height: 175, weight: 68, hairColor: "brown"},
  
  // List
  tags: ["IT", "happy", "geek"],
  
  // Binary
  avatar: "data:image/png;base64,iVBORw0KGgo...",

  // Vector (using AI.VECTOR function)
  embedding: ai.vector([0.12, 0.45, 0.78, 0.33])
})