Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.helix-db.com/llms.txt

Use this file to discover all available pages before exploring further.

For the complete documentation index optimized for AI agents, see llms.txt.

Upsert Edges using UpsertE  

Create new edges or update existing ones with insert-or-update semantics.
UpsertE({properties})::From(node1)::To(node2)
UpsertE is a traversal step that operates on an existing traversal context. The type comes from the preceding traversal (E<Type>), not from the upsert call itself. If an edge already exists between the specified nodes, it is updated; if no edge is found, a new edge is created.
Edge connections (::From() and ::To()) are required for UpsertE. The order of From and To is flexible. Properties are also required.

Example 1: Basic edge upsert with properties

QUERY UpsertFriendship(id1: ID, id2: ID, since: String) =>
    person1 <- N<Person>(id1)
    person2 <- N<Person>(id2)
    existing <- E<Knows>
    edge <- existing::UpsertE({since: since})::From(person1)::To(person2)
    RETURN edge

QUERY CreatePerson(name: String, age: U32) =>
    person <- AddN<Person>({name: name, age: age})
    RETURN person
Here’s how to run the query using the SDKs or curl
from helix.client import Client

client = Client(local=True, port=6969)

# Create two people
alice = client.query("CreatePerson", {
    "name": "Alice",
    "age": 25,
})[0]["person"]

bob = client.query("CreatePerson", {
    "name": "Bob",
    "age": 28,
})[0]["person"]

# First call creates the edge
result = client.query("UpsertFriendship", {
    "id1": alice["id"],
    "id2": bob["id"],
    "since": "2024-01-15",
})

print("Created edge:", result)

# Subsequent calls update the existing edge (no duplicate created)
result = client.query("UpsertFriendship", {
    "id1": alice["id"],
    "id2": bob["id"],
    "since": "2024-06-20",
})

print("Upserted edge:", result)

Example 2: Upsert edge with multiple properties

QUERY UpsertFriendshipWithProps(id1: ID, id2: ID, since: String, strength: F32) =>
    person1 <- N<Person>(id1)
    person2 <- N<Person>(id2)
    existing <- E<Friendship>
    edge <- existing::UpsertE({since: since, strength: strength})::From(person1)::To(person2)
    RETURN edge

QUERY CreatePerson(name: String, age: U32) =>
    person <- AddN<Person>({name: name, age: age})
    RETURN person
Here’s how to run the query using the SDKs or curl
from helix.client import Client

client = Client(local=True, port=6969)

alice = client.query("CreatePerson", {
    "name": "Alice",
    "age": 25,
})[0]["person"]

bob = client.query("CreatePerson", {
    "name": "Bob",
    "age": 28,
})[0]["person"]

# Create friendship with properties
result = client.query("UpsertFriendshipWithProps", {
    "id1": alice["id"],
    "id2": bob["id"],
    "since": "2024-01-15",
    "strength": 0.85,
})

print("Created friendship:", result)

# Update the friendship strength
result = client.query("UpsertFriendshipWithProps", {
    "id1": alice["id"],
    "id2": bob["id"],
    "since": "2024-01-15",
    "strength": 0.95,
})

print("Updated friendship:", result)

Example 3: Flexible From/To ordering

The ::From() and ::To() can be specified in either order.
QUERY UpsertEdgeToFrom(id1: ID, id2: ID, since: String) =>
    person1 <- N<Person>(id1)
    person2 <- N<Person>(id2)
    existing <- E<Knows>
    // To and From can be in either order
    edge <- existing::UpsertE({since: since})::To(person2)::From(person1)
    RETURN edge

How Upsert differs from Add

OperationBehavior
AddEAlways creates a new edge (can create duplicates)
UpsertEOperates on traversal context: updates if edge exists between nodes, creates if not
When updating, UpsertE merges properties: it updates specified properties while preserving any existing properties that aren’t included in the upsert.