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

Conditional Steps

⚠️ 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.

Filtering with WHERE  

Filter elements based on specific conditions.

::WHERE(<condition>)
::WHERE(_::{property}::COMPARISON(value))

ℹ️ Note

The condition in the WHERE step must evaluate to a boolean value. If the condition is not met, the element will be filtered out from the results.

⚠️ Warning

When using the SDKs or curling the endpoint, the query name must match what is defined in the queries.hx file exactly.

Comparison Operations

The following operations can be used to compare values. EQ and NEQ can be used to compare strings, booleans, and numbers. GT, GTE, LT, and LTE can only be used to compare numbers.

String, Boolean, and Number Operations

OperationDescriptionExample
::EQ(value)Equals::WHERE(_::{status}::EQ("active"))
::NEQ(value)Not equals::WHERE(_::{age}::NEQ(25))

Number Operations

OperationDescriptionExample
::GT(value)Greater than::WHERE(_::{age}::GT(25))
::LT(value)Less than::WHERE(_::{age}::LT(30))
::GTE(value)Greater than or equal::WHERE(_::{rating}::GTE(4.5))
::LTE(value)Less than or equal::WHERE(_::{priority}::LTE(2))

String Operations

OperationDescriptionExample
::CONTAINS(value)String contains substring::WHERE(_::{name}::CONTAINS("john"))
::CONTAINS(object)Array contains object::WHERE(_::Out<Follows>::CONTAINS(user))

Array/Set Operations

OperationDescriptionExample
::IS_IN(array)Value exists in array::WHERE(_::{status}::IS_IN(["active", "pending"]))

Example 1: Basic filtering with WHERE

QUERY GetAdultUsers () =>
    adult_users <- N<User>::WHERE(_::{age}::GT(18))
    RETURN adult_users

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

Here’s how to run the query using the SDKs or curl

from helix.client import Client

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

users = [
    {"name": "Alice", "age": 25, "email": "alice@example.com"},
    {"name": "Bob", "age": 16, "email": "bob@example.com"},
    {"name": "Charlie", "age": 30, "email": "charlie@example.com"},
    {"name": "Diana", "age": 17, "email": "diana@example.com"},
]

for user in users:
    client.query("CreateUser", user)

result = client.query("GetAdultUsers", {})
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 users = vec![
        ("Alice", 25, "alice@example.com"),
        ("Bob", 16, "bob@example.com"),
        ("Charlie", 30, "charlie@example.com"),
        ("Diana", 17, "diana@example.com"),
    ];

    for (name, age, email) in &users {
        let _created: serde_json::Value = client.query("CreateUser", &json!({
            "name": name,
            "age": age,
            "email": email,
        })).await?;
    }

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

    Ok(())
}
package main

import (
    "fmt"
    "log"

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

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

    users := []map[string]any{
        {"name": "Alice", "age": uint8(25), "email": "alice@example.com"},
        {"name": "Bob", "age": uint8(16), "email": "bob@example.com"},
        {"name": "Charlie", "age": uint8(30), "email": "charlie@example.com"},
        {"name": "Diana", "age": uint8(17), "email": "diana@example.com"},
    }

    for _, user := range users {
        var created map[string]any
        if err := client.Query("CreateUser", helix.WithData(user)).Scan(&created); err != nil {
            log.Fatalf("CreateUser failed: %s", err)
        }
    }

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

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

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

    const users = [
        { name: "Alice", age: 25, email: "alice@example.com" },
        { name: "Bob", age: 16, email: "bob@example.com" },
        { name: "Charlie", age: 30, email: "charlie@example.com" },
        { name: "Diana", age: 17, email: "diana@example.com" },
    ];

    for (const user of users) {
        await client.query("CreateUser", user);
    }

    const result = await client.query("GetAdultUsers", {});
    console.log("Adult users:", result);
}

main().catch((err) => {
    console.error("GetAdultUsers query failed:", err);
});
curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","age":25,"email":"alice@example.com"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob","age":16,"email":"bob@example.com"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Charlie","age":30,"email":"charlie@example.com"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Diana","age":17,"email":"diana@example.com"}'

curl -X POST \
  http://localhost:6969/GetAdultUsers \
  -H 'Content-Type: application/json' \
  -d '{}'

💡 Tip

For multiple conditions, see Multiple Conditional Steps.

Example 2: String and equality filtering

QUERY GetActiveUsers (status: String) =>
    active_users <- N<User>::WHERE(_::{status}::EQ(status))
    RETURN active_users

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

Here’s how to run the query using the SDKs or curl

from helix.client import Client

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

users = [
    {"name": "Alice", "age": 25, "email": "alice@example.com", "status": "active"},
    {"name": "Bob", "age": 30, "email": "bob@example.com", "status": "inactive"},
    {"name": "Charlie", "age": 28, "email": "charlie@example.com", "status": "active"},
    {"name": "Diana", "age": 22, "email": "diana@example.com", "status": "pending"},
]

for user in users:
    client.query("CreateUser", user)

result = client.query("GetActiveUsers", {"status": "active"})
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 users = vec![
        ("Alice", 25, "alice@example.com", "active"),
        ("Bob", 30, "bob@example.com", "inactive"),
        ("Charlie", 28, "charlie@example.com", "active"),
        ("Diana", 22, "diana@example.com", "pending"),
    ];

    for (name, age, email, status) in &users {
        let _created: serde_json::Value = client.query("CreateUser", &json!({
            "name": name,
            "age": age,
            "email": email,
            "status": status,
        })).await?;
    }

    let result: serde_json::Value = client.query("GetActiveUsers", &json!({
        "status": "active"
    })).await?;
    println!("Active users: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"

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

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

    users := []map[string]any{
        {"name": "Alice", "age": uint8(25), "email": "alice@example.com", "status": "active"},
        {"name": "Bob", "age": uint8(30), "email": "bob@example.com", "status": "inactive"},
        {"name": "Charlie", "age": uint8(28), "email": "charlie@example.com", "status": "active"},
        {"name": "Diana", "age": uint8(22), "email": "diana@example.com", "status": "pending"},
    }

    for _, user := range users {
        var created map[string]any
        if err := client.Query("CreateUser", helix.WithData(user)).Scan(&created); err != nil {
            log.Fatalf("CreateUser failed: %s", err)
        }
    }

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

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

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

    const users = [
        { name: "Alice", age: 25, email: "alice@example.com", status: "active" },
        { name: "Bob", age: 30, email: "bob@example.com", status: "inactive" },
        { name: "Charlie", age: 28, email: "charlie@example.com", status: "active" },
        { name: "Diana", age: 22, email: "diana@example.com", status: "pending" },
    ];

    for (const user of users) {
        await client.query("CreateUser", user);
    }

    const result = await client.query("GetActiveUsers", { status: "active" });
    console.log("Active users:", result);
}

main().catch((err) => {
    console.error("GetActiveUsers query failed:", err);
});
curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","age":25,"email":"alice@example.com","status":"active"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob","age":30,"email":"bob@example.com","status":"inactive"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Charlie","age":28,"email":"charlie@example.com","status":"active"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Diana","age":22,"email":"diana@example.com","status":"pending"}'

curl -X POST \
  http://localhost:6969/GetActiveUsers \
  -H 'Content-Type: application/json' \
  -d '{"status":"active"}'

Filter by Relationships with EXISTS  

Returns true if a traversal has any results. Otherwise, it returns false.

EXISTS(<traversal>)

Example 1: Using EXISTS for relationship filtering

QUERY GetUsersWithFollowers () =>
    users <- N<User>::WHERE(EXISTS(_::In<Follows>))
    RETURN users

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

QUERY CreateFollow (follower_id: ID, following_id: ID) =>
    follower <- N<User>(follower_id)
    following <- N<User>(following_id)
    AddE<Follows>::From(follower)::To(following)
    RETURN "Success"
N::User {
    name: String,
    age: U8,
    email: String
}

E::Follows {
    From: User,
    To: User
}

Here’s how to run the query using the SDKs or curl

from helix.client import Client

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

users = [
    {"name": "Alice", "age": 25, "email": "alice@example.com"},
    {"name": "Bob", "age": 30, "email": "bob@example.com"},
    {"name": "Charlie", "age": 28, "email": "charlie@example.com"},
]

user_ids = []
for user in users:
    result = client.query("CreateUser", user)
    user_ids.append(result[0]["user"]["id"])

client.query("CreateFollow", {"follower_id": user_ids[1], "following_id": user_ids[0]})
client.query("CreateFollow", {"follower_id": user_ids[2], "following_id": user_ids[0]})

result = client.query("GetUsersWithFollowers", {})
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 users = vec![
        ("Alice", 25, "alice@example.com"),
        ("Bob", 30, "bob@example.com"),
        ("Charlie", 28, "charlie@example.com"),
    ];

    let mut user_ids = Vec::new();
    for (name, age, email) in &users {
        let result: serde_json::Value = client.query("CreateUser", &json!({
            "name": name,
            "age": age,
            "email": email,
        })).await?;
        user_ids.push(result["user"]["id"].as_str().unwrap().to_string());
    }

    let _follow1: serde_json::Value = client.query("CreateFollow", &json!({
        "follower_id": user_ids[1],
        "following_id": user_ids[0]
    })).await?;

    let _follow2: serde_json::Value = client.query("CreateFollow", &json!({
        "follower_id": user_ids[2],
        "following_id": user_ids[0]
    })).await?;

    let result: serde_json::Value = client.query("GetUsersWithFollowers", &json!({})).await?;
    println!("Users with followers: {result:#?}");

    Ok(())
}
package main

import (
    "fmt"
    "log"

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

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

    users := []map[string]any{
        {"name": "Alice", "age": uint8(25), "email": "alice@example.com"},
        {"name": "Bob", "age": uint8(30), "email": "bob@example.com"},
        {"name": "Charlie", "age": uint8(28), "email": "charlie@example.com"},
    }

    var userIDs []string
    for _, user := range users {
        var created map[string]any
        if err := client.Query("CreateUser", helix.WithData(user)).Scan(&created); err != nil {
            log.Fatalf("CreateUser failed: %s", err)
        }
        userIDs = append(userIDs, created["user"].(map[string]any)["id"].(string))
    }

    followPayload1 := map[string]any{
        "follower_id":  userIDs[1],
        "following_id": userIDs[0],
    }
    var follow1 map[string]any
    if err := client.Query("CreateFollow", helix.WithData(followPayload1)).Scan(&follow1); err != nil {
        log.Fatalf("CreateFollow failed: %s", err)
    }

    followPayload2 := map[string]any{
        "follower_id":  userIDs[2],
        "following_id": userIDs[0],
    }
    var follow2 map[string]any
    if err := client.Query("CreateFollow", helix.WithData(followPayload2)).Scan(&follow2); err != nil {
        log.Fatalf("CreateFollow failed: %s", err)
    }

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

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

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

    const users = [
        { name: "Alice", age: 25, email: "alice@example.com" },
        { name: "Bob", age: 30, email: "bob@example.com" },
        { name: "Charlie", age: 28, email: "charlie@example.com" },
    ];

    const userIds: string[] = [];
    for (const user of users) {
        const result = await client.query("CreateUser", user);
        userIds.push(result.user.id);
    }

    await client.query("CreateFollow", {
        follower_id: userIds[1],
        following_id: userIds[0]
    });

    await client.query("CreateFollow", {
        follower_id: userIds[2],
        following_id: userIds[0]
    });

    const result = await client.query("GetUsersWithFollowers", {});
    console.log("Users with followers:", result);
}

main().catch((err) => {
    console.error("GetUsersWithFollowers query failed:", err);
});
curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alice","age":25,"email":"alice@example.com"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Bob","age":30,"email":"bob@example.com"}'

curl -X POST \
  http://localhost:6969/CreateUser \
  -H 'Content-Type: application/json' \
  -d '{"name":"Charlie","age":28,"email":"charlie@example.com"}'

curl -X POST \
  http://localhost:6969/CreateFollow \
  -H 'Content-Type: application/json' \
  -d '{"follower_id":"<bob_id>","following_id":"<alice_id>"}'

curl -X POST \
  http://localhost:6969/CreateFollow \
  -H 'Content-Type: application/json' \
  -d '{"follower_id":"<charlie_id>","following_id":"<alice_id>"}'

curl -X POST \
  http://localhost:6969/GetUsersWithFollowers \
  -H 'Content-Type: application/json' \
  -d '{}'