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
    • Overview
    • CASE
    • LET Value Expression
    • Value Query Expression
    • Count 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

MERGE

Overview

The MERGE statement matches a pattern in the graph; if the pattern is not found, it creates the missing nodes and edges. Optional ON MATCH SET and ON INSERT SET sub-clauses let you apply different property updates depending on whether the entity already existed or was newly created.

MERGE differs from INSERT OVERWRITE and UPSERT in matching mode: INSERT OVERWRITE and UPSERT key on _id only, while MERGE matches on the full pattern including labels and property values.

Syntax
<merge statement> ::=
  "MERGE" <graph pattern>
  [ "ON INSERT SET" <set item list> ]
  [ "ON MATCH SET" <set item list> ]

Details

  • MERGE examines the pattern as a whole. If every node and edge in the pattern can be bound, the existing match is used; otherwise the missing pieces are created.
  • ON INSERT SET runs only on rows where the pattern was newly created.
  • ON MATCH SET runs once per row produced by an existing match.
  • Both ON MATCH SET and ON INSERT SET are optional and may appear in either order.

Merging Nodes

Match a Person named Alice; create one if it does not exist:

GQL
MERGE (p:Person {name: 'Alice'})
RETURN p

If no such node exists, a Person node named Alice is created. If one exists, it is bound to p and returned without modification.

ON INSERT SET

Set additional properties only when the node is newly created:

GQL
MERGE (p:Person {email: '[email protected]'})
ON INSERT SET p.name = 'Alice', p.createdAt = date()
RETURN p

A new Person carries email, name, and createdAt. An existing Person is returned unchanged.

ON MATCH SET

Set properties only when the pattern matched an existing entity:

GQL
MERGE (p:Person {email: '[email protected]'})
ON MATCH SET p.lastSeen = date()
RETURN p

A new Person carries email only. An existing Person is added with lastSeen.

Combining ON INSERT SET and ON MATCH SET

Differentiate the two paths in a single statement:

GQL
MERGE (p:Person {email: '[email protected]'})
ON INSERT SET p.name = 'Alice', p.visits = 1
ON MATCH SET p.visits = p.visits + 1
RETURN p

Each invocation creates the row on first call and increments visits on every subsequent call.

Merging Edges

Use MATCH to bind the endpoints, then MERGE the edge:

GQL
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:Knows]->(b)
ON INSERT SET r.since = 2024
ON MATCH SET r.interactions = r.interactions + 1
RETURN r

If a Knows edge already runs from Alice to Bob, its interactions counter is incremented; otherwise a new edge is created with since = 2024.

NOTE

Edge _id in MERGE: If you supply _id inside the edge property specification (e.g., MERGE (a)-[r:Knows {_id: 'tx-123'}]->(b)), the graph must have edge _id enabled. See Node and Edge IDs.

Merging Whole Patterns

MERGE matches the pattern as a whole. If the entire pattern is found, no changes are made. If it is not, the whole pattern is created, including elements that exist elsewhere in the graph.

GQL
MERGE (:Person {name: 'Alice'})-[:Knows]->(:Person {name: 'Bob'})

For example, if Alice already exists but Bob does not exist, the path as a whole does not match. MERGE then creates a new Alice node, a Bob node, and the Knows edge between them, leaving the graph with two Alice nodes.

Tip: To avoid creating duplicate endpoints, split the pattern into separate MERGE statements — one per element. Each MERGE binds its variable to a single node, so the third MERGE only has the edge left to look for:

GQL
MERGE (a:Person {name: 'Alice'})
MERGE (b:Person {name: 'Bob1'})
MERGE (a)-[:Knows]->(b)

For the example case where Alice exists and Bob does not, this produces 1 new node (Bob) and 1 new edge, no duplicate Alice.

Matching Multiple Elements

MERGE inserts only when the pattern matches nothing. If the pattern already matches more than one element, MERGE takes the match branch for all of them: it creates nothing, runs ON MATCH SET on every matched element, and binds the variable to each (so RETURN yields one row per match). MERGE does not deduplicate or enforce uniqueness, so pre-existing duplicates remain and the statement fans out across all of them.

This applies to both nodes and edges:

GQL
-- If two Person nodes named 'Alex' exist, ON MATCH SET runs on both
MERGE (p:Person {name: 'Alex'})
ON MATCH SET p.seen = p.seen + 1
ON INSERT SET p.seen = 1

-- If two Knows edges exist from Alice to Bob (parallel edges), ON MATCH SET runs on both
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:Knows]->(b)
ON MATCH SET r.seen = r.seen + 1
ON INSERT SET r.seen = 1

Merge on a unique key (such as _id) when you need the pattern to match at most one element.