Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Traversals From Edges

⚠️ Warning

HelixQL is deprecated in HelixDB v2. Queries are now written with the Rust DSL and dispatched as JSON — see the Querying guide. This section is kept as a reference for legacy HelixQL projects.

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

The Idea

When you have an edge, you can traverse to its connected endpoints. Use ::FromN or ::FromV to get the source node or vector, and ::ToN or ::ToV to get the destination node or vector.

::FromN   Source Node

Return the node that the edge originates from.

::FromN

Example 1: Getting the user from a document creation edge

QUERY GetCreatorFromEdge (creation_id: ID) =>
    creator <- E<Creates>(creation_id)::FromN
    RETURN creator

QUERY CreateUser (name: String, email: String) =>
    user <- AddN<User>({
        name: name,
        email: email,
    })
    RETURN user

QUERY CreateDocument (user_id: ID, content: String, vector: [F64]) =>
    document <- AddV<Document>(vector, {
        content: content
    })
    creation_edge <- AddE<Creates>::From(user_id)::To(document)
    RETURN creation_edge
N::User {
    name: String,
    email: String,
}

V::Document {
    content: String
}

E::Creates {
    From: User,
    To: Document
}
from helix.client import Client

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

alice = client.query("CreateUser", {"name": "Alice", "email": "alice@example.com"})
alice_id = alice[0]["user"]["id"]

creation = client.query("CreateDocument", {
    "user_id": alice_id,
    "content": "This is my first document",
    "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
})
creation_id = creation[0]["creation_edge"]["id"]

result = client.query("GetCreatorFromEdge", {
    "creation_id": creation_id,
})
print(result)
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let alice: serde_json::Value = client.query("CreateUser", &json!({
        "name": "Alice",
        "email": "alice@example.com",
    })).await?;
    let alice_id = alice["user"]["id"].as_str().unwrap().to_string();

    let creation: serde_json::Value = client.query("CreateDocument", &json!({
        "user_id": alice_id,
        "content": "This is my first document",
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
    })).await?;
    let creation_id = creation["creation_edge"]["id"].as_str().unwrap().to_string();

    let result: serde_json::Value = client.query("GetCreatorFromEdge", &json!({
        "creation_id": creation_id,
    })).await?;
    println!("GetCreatorFromEdge result: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    var alice map[string]any
    if err := client.Query("CreateUser",
        helix.WithData(map[string]any{"name": "Alice", "email": "alice@example.com"}),
    ).Scan(&alice); err != nil {
        log.Fatalf("CreateUser (Alice) failed: %s", err)
    }

    aliceID := alice["user"].(map[string]any)["id"].(string)

    var creation map[string]any
    if err := client.Query("CreateDocument",
        helix.WithData(map[string]any{
            "user_id": aliceID,
            "content": "This is my first document",
            "vector": []float64{0.1, 0.2, 0.3, 0.4, 0.5},
        }),
    ).Scan(&creation); err != nil {
        log.Fatalf("CreateDocument failed: %s", err)
    }

    creationID := creation["creation_edge"].(map[string]any)["id"].(string)

    var result map[string]any
    if err := client.Query("GetCreatorFromEdge",
        helix.WithData(map[string]any{"creation_id": creationID}),
    ).Scan(&result); err != nil {
        log.Fatalf("GetCreatorFromEdge failed: %s", err)
    }

    fmt.Printf("GetCreatorFromEdge result: %#v\n", result)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const alice = await client.query("CreateUser", {
        name: "Alice",
        email: "alice@example.com",
    });

    const creation = await client.query("CreateDocument", {
        user_id: alice.user.id,
        content: "This is my first document",
        vector: [0.1, 0.2, 0.3, 0.4, 0.5],
    });

    const result = await client.query("GetCreatorFromEdge", {
        creation_id: creation.creation_edge.id,
    });

    console.log("GetCreatorFromEdge result:", result);
}

main().catch((err) => {
    console.error("GetCreatorFromEdge query failed:", err);
});
alice=$(curl -s -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","email":"alice@example.com"}')
alice_id=$(echo "$alice" | jq -r '.user.id')

creation=$(curl -s -X POST \
  http://localhost:6969/CreateDocument \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"'"$alice_id"'","content":"This is my first document","vector":[0.1,0.2,0.3,0.4,0.5]}')
creation_id=$(echo "$creation" | jq -r '.creation_edge.id')

curl -s -X POST \
  http://localhost:6969/GetCreatorFromEdge \
  -H 'Content-Type: application/json' \
  -d '{"creation_id":"'"$creation_id"'"}'

::FromV   Source Vector

Return the vector that the edge originates from.

::FromV

Example 1: Getting the source document from a mentions edge

QUERY GetMentionSource (mention_id: ID) =>
    source_doc <- E<MentionsUser>(mention_id)::FromV
    RETURN source_doc

QUERY CreateUser (name: String, email: String) =>
    user <- AddN<User>({
        name: name,
        email: email,
    })
    RETURN user

QUERY CreateDocument (content: String, vector: [F64]) =>
    document <- AddV<Document>(vector, {
        content: content
    })
    RETURN document

QUERY LinkMention (document_id: ID, user_id: ID) =>
    mention_edge <- AddE<MentionsUser>::From(document_id)::To(user_id)
    RETURN mention_edge
V::Document {
    content: String
}

N::User {
    name: String,
    email: String,
}

E::MentionsUser {
    From: Document,
    To: User
}
from helix.client import Client

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

alice = client.query("CreateUser", {"name": "Alice", "email": "alice@example.com"})
alice_id = alice[0]["user"]["id"]

document = client.query("CreateDocument", {
    "content": "This document mentions @alice",
    "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
})
document_id = document[0]["document"]["id"]

mention = client.query("LinkMention", {
    "document_id": document_id,
    "user_id": alice_id,
})
mention_id = mention[0]["mention_edge"]["id"]

source = client.query("GetMentionSource", {
    "mention_id": mention_id,
})
print(source)
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let alice: serde_json::Value = client.query("CreateUser", &json!({
        "name": "Alice",
        "email": "alice@example.com",
    })).await?;
    let alice_id = alice["user"]["id"].as_str().unwrap().to_string();

    let document: serde_json::Value = client.query("CreateDocument", &json!({
        "content": "This document mentions @alice",
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
    })).await?;
    let document_id = document["document"]["id"].as_str().unwrap().to_string();

    let mention: serde_json::Value = client.query("LinkMention", &json!({
        "document_id": document_id,
        "user_id": alice_id,
    })).await?;
    let mention_id = mention["mention_edge"]["id"].as_str().unwrap().to_string();

    let source: serde_json::Value = client.query("GetMentionSource", &json!({
        "mention_id": mention_id,
    })).await?;
    println!("GetMentionSource result: {source:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    var alice map[string]any
    if err := client.Query("CreateUser",
        helix.WithData(map[string]any{"name": "Alice", "email": "alice@example.com"}),
    ).Scan(&alice); err != nil {
        log.Fatalf("CreateUser (Alice) failed: %s", err)
    }

    aliceID := alice["user"].(map[string]any)["id"].(string)

    var document map[string]any
    if err := client.Query("CreateDocument",
        helix.WithData(map[string]any{
            "content": "This document mentions @alice",
            "vector": []float64{0.1, 0.2, 0.3, 0.4, 0.5},
        }),
    ).Scan(&document); err != nil {
        log.Fatalf("CreateDocument failed: %s", err)
    }

    documentID := document["document"].(map[string]any)["id"].(string)

    var mention map[string]any
    if err := client.Query("LinkMention",
        helix.WithData(map[string]any{
            "document_id": documentID,
            "user_id": aliceID,
        }),
    ).Scan(&mention); err != nil {
        log.Fatalf("LinkMention failed: %s", err)
    }

    mentionID := mention["mention_edge"].(map[string]any)["id"].(string)

    var source map[string]any
    if err := client.Query("GetMentionSource",
        helix.WithData(map[string]any{"mention_id": mentionID}),
    ).Scan(&source); err != nil {
        log.Fatalf("GetMentionSource failed: %s", err)
    }

    fmt.Printf("GetMentionSource result: %#v\n", source)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const alice = await client.query("CreateUser", {
        name: "Alice",
        email: "alice@example.com",
    });

    const document = await client.query("CreateDocument", {
        content: "This document mentions @alice",
        vector: [0.1, 0.2, 0.3, 0.4, 0.5],
    });

    const mention = await client.query("LinkMention", {
        document_id: document.document.id,
        user_id: alice.user.id,
    });

    const source = await client.query("GetMentionSource", {
        mention_id: mention.mention_edge.id,
    });

    console.log("GetMentionSource result:", source);
}

main().catch((err) => {
    console.error("GetMentionSource query failed:", err);
});
alice=$(curl -s -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","email":"alice@example.com"}')
alice_id=$(echo "$alice" | jq -r '.user.id')

document=$(curl -s -X POST \
  http://localhost:6969/CreateDocument \
  -H 'Content-Type: application/json' \
  -d '{"content":"This document mentions @alice","vector":[0.1,0.2,0.3,0.4,0.5]}')
document_id=$(echo "$document" | jq -r '.document.id')

mention=$(curl -s -X POST \
  http://localhost:6969/LinkMention \
  -H 'Content-Type: application/json' \
  -d '{"document_id":"'"$document_id"'","user_id":"'"$alice_id"'"}')
mention_id=$(echo "$mention" | jq -r '.mention_edge.id')

curl -s -X POST \
  http://localhost:6969/GetMentionSource \
  -H 'Content-Type: application/json' \
  -d '{"mention_id":"'"$mention_id"'"}'

::ToN   Destination Node

Return the node that the edge points to.

::ToN

Example 1: Getting the followed user from a follow edge

QUERY GetFollowedUser (follow_id: ID) =>
    followed_user <- E<Follows>(follow_id)::ToN
    RETURN followed_user

QUERY CreateUser (name: String, email: String) =>
    user <- AddN<User>({
        name: name,
        email: email,
    })
    RETURN user

QUERY FollowUser (follower_id: ID, followed_id: ID, since: String) =>
    follow_edge <- AddE<Follows>::From(follower_id)::To(followed_id)
    RETURN follow_edge
N::User {
    name: String,
    email: String,
}

E::Follows {
    From: User,
    To: User
}
from helix.client import Client
from datetime import datetime

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

alice = client.query("CreateUser", {"name": "Alice", "email": "alice@example.com"})
alice_id = alice[0]["user"]["id"]

bob = client.query("CreateUser", {"name": "Bob", "email": "bob@example.com"})
bob_id = bob[0]["user"]["id"]

since_value = datetime.now().isoformat()

follow = client.query("FollowUser", {
    "follower_id": alice_id,
    "followed_id": bob_id,
    "since": since_value,
})
follow_id = follow[0]["follow_edge"]["id"]

followed_user = client.query("GetFollowedUser", {
    "follow_id": follow_id,
})
print(followed_user)
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;
use chrono::Utc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);
    let since_value = Utc::now().to_rfc3339();

    let alice: serde_json::Value = client.query("CreateUser", &json!({
        "name": "Alice",
        "email": "alice@example.com",
    })).await?;
    let alice_id = alice["user"]["id"].as_str().unwrap().to_string();

    let bob: serde_json::Value = client.query("CreateUser", &json!({
        "name": "Bob",
        "email": "bob@example.com",
    })).await?;
    let bob_id = bob["user"]["id"].as_str().unwrap().to_string();

    let follow: serde_json::Value = client.query("FollowUser", &json!({
        "follower_id": alice_id,
        "followed_id": bob_id,
        "since": since_value,
    })).await?;
    let follow_id = follow["follow_edge"]["id"].as_str().unwrap().to_string();

    let followed_user: serde_json::Value = client.query("GetFollowedUser", &json!({
        "follow_id": follow_id,
    })).await?;
    println!("GetFollowedUser result: {followed_user:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")
    sinceValue := time.Now().UTC().Format(time.RFC3339)

    var alice map[string]any
    if err := client.Query("CreateUser",
        helix.WithData(map[string]any{"name": "Alice", "email": "alice@example.com"}),
    ).Scan(&alice); err != nil {
        log.Fatalf("CreateUser (Alice) failed: %s", err)
    }

    var bob map[string]any
    if err := client.Query("CreateUser",
        helix.WithData(map[string]any{"name": "Bob", "email": "bob@example.com"}),
    ).Scan(&bob); err != nil {
        log.Fatalf("CreateUser (Bob) failed: %s", err)
    }

    aliceID := alice["user"].(map[string]any)["id"].(string)
    bobID := bob["user"].(map[string]any)["id"].(string)

    var follow map[string]any
    if err := client.Query("FollowUser",
        helix.WithData(map[string]any{
            "follower_id": aliceID,
            "followed_id": bobID,
            "since": sinceValue,
        }),
    ).Scan(&follow); err != nil {
        log.Fatalf("FollowUser failed: %s", err)
    }

    followID := follow["follow_edge"].(map[string]any)["id"].(string)

    var followedUser map[string]any
    if err := client.Query("GetFollowedUser",
        helix.WithData(map[string]any{"follow_id": followID}),
    ).Scan(&followedUser); err != nil {
        log.Fatalf("GetFollowedUser failed: %s", err)
    }

    fmt.Printf("GetFollowedUser result: %#v\n", followedUser)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");
    const sinceValue = new Date().toISOString();

    const alice = await client.query("CreateUser", {
        name: "Alice",
        email: "alice@example.com",
    });

    const bob = await client.query("CreateUser", {
        name: "Bob",
        email: "bob@example.com",
    });

    const follow = await client.query("FollowUser", {
        follower_id: alice.user.id,
        followed_id: bob.user.id,
        since: sinceValue,
    });

    const followedUser = await client.query("GetFollowedUser", {
        follow_id: follow.follow_edge.id,
    });

    console.log("GetFollowedUser result:", followedUser);
}

main().catch((err) => {
    console.error("GetFollowedUser query failed:", err);
});
alice=$(curl -s -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","email":"alice@example.com"}')
alice_id=$(echo "$alice" | jq -r '.user.id')

bob=$(curl -s -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob","email":"bob@example.com"}')
bob_id=$(echo "$bob" | jq -r '.user.id')

since=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

follow=$(curl -s -X POST \
  http://localhost:6969/FollowUser \
  -H 'Content-Type: application/json' \
  -d '{"follower_id":"'"$alice_id"'","followed_id":"'"$bob_id"'","since":"'"$since"'"}')
follow_id=$(echo "$follow" | jq -r '.follow_edge.id')

curl -s -X POST \
  http://localhost:6969/GetFollowedUser \
  -H 'Content-Type: application/json' \
  -d '{"follow_id":"'"$follow_id"'"}'

::ToV   Destination Vector

Return the vector that the edge points to.

::ToV

Example 1: Inspecting the document vector

QUERY GetDocumentVector (creation_id: ID) =>
    document_vector <- E<Creates>(creation_id)::ToV
    RETURN document_vector

QUERY CreateUser (name: String, email: String) =>
    user <- AddN<User>({
        name: name,
        email: email,
    })
    RETURN user

QUERY CreateDocument (user_id: ID, content: String, vector: [F64]) =>
    document <- AddV<Document>(vector, {
        content: content
    })
    creation_edge <- AddE<Creates>::From(user_id)::To(document)
    RETURN creation_edge
N::User {
    name: String,
    email: String,
}

V::Document {
    content: String
}

E::Creates {
    From: User,
    To: Document
}
from helix.client import Client

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

alice = client.query("CreateUser", {"name": "Alice", "email": "alice@example.com"})
alice_id = alice[0]["user"]["id"]

creation = client.query("CreateDocument", {
    "user_id": alice_id,
    "content": "This is my first document",
    "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
})
creation_id = creation[0]["creation_edge"]["id"]

vector = client.query("GetDocumentVector", {
    "creation_id": creation_id,
})
print(vector)
use helix_rs::{HelixDB, HelixDBClient};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = HelixDB::new(Some("http://localhost"), Some(6969), None);

    let alice: serde_json::Value = client.query("CreateUser", &json!({
        "name": "Alice",
        "email": "alice@example.com",
    })).await?;
    let alice_id = alice["user"]["id"].as_str().unwrap().to_string();

    let creation: serde_json::Value = client.query("CreateDocument", &json!({
        "user_id": alice_id,
        "content": "This is my first document",
        "vector": [0.1, 0.2, 0.3, 0.4, 0.5],
    })).await?;
    let creation_id = creation["creation_edge"]["id"].as_str().unwrap().to_string();

    let vector: serde_json::Value = client.query("GetDocumentVector", &json!({
        "creation_id": creation_id,
    })).await?;
    println!("GetDocumentVector result: {vector:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"

    "github.com/HelixDB/helix-go"
)

func main() {
    client := helix.NewClient("http://localhost:6969")

    var alice map[string]any
    if err := client.Query("CreateUser",
        helix.WithData(map[string]any{"name": "Alice", "email": "alice@example.com"}),
    ).Scan(&alice); err != nil {
        log.Fatalf("CreateUser (Alice) failed: %s", err)
    }

    aliceID := alice["user"].(map[string]any)["id"].(string)

    var creation map[string]any
    if err := client.Query("CreateDocument",
        helix.WithData(map[string]any{
            "user_id": aliceID,
            "content": "This is my first document",
            "vector": []float64{0.1, 0.2, 0.3, 0.4, 0.5},
        }),
    ).Scan(&creation); err != nil {
        log.Fatalf("CreateDocument failed: %s", err)
    }

    creationID := creation["creation_edge"].(map[string]any)["id"].(string)

    var vector map[string]any
    if err := client.Query("GetDocumentVector",
        helix.WithData(map[string]any{"creation_id": creationID}),
    ).Scan(&vector); err != nil {
        log.Fatalf("GetDocumentVector failed: %s", err)
    }

    fmt.Printf("GetDocumentVector result: %#v\n", vector)
}
import HelixDB from "helix-ts";

async function main() {
    const client = new HelixDB("http://localhost:6969");

    const alice = await client.query("CreateUser", {
        name: "Alice",
        email: "alice@example.com",
    });

    const creation = await client.query("CreateDocument", {
        user_id: alice.user.id,
        content: "This is my first document",
        vector: [0.1, 0.2, 0.3, 0.4, 0.5],
    });

    const vector = await client.query("GetDocumentVector", {
        creation_id: creation.creation_edge.id,
    });

    console.log("GetDocumentVector result:", vector);
}

main().catch((err) => {
    console.error("GetDocumentVector query failed:", err);
});
alice=$(curl -s -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","email":"alice@example.com"}')
alice_id=$(echo "$alice" | jq -r '.user.id')

creation=$(curl -s -X POST \
  http://localhost:6969/CreateDocument \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"'"$alice_id"'","content":"This is my first document","vector":[0.1,0.2,0.3,0.4,0.5]}')
creation_id=$(echo "$creation" | jq -r '.creation_edge.id')

curl -s -X POST \
  http://localhost:6969/GetDocumentVector \
  -H 'Content-Type: application/json' \
  -d '{"creation_id":"'"$creation_id"'"}'

ℹ️ Note

Combine edge traversals with property filtering or continue traversing from the destination. See the Property Access and Traversals From Nodes guides.