Skip to main content

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.