HelixQL Language Reference
⚠️ 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.
Every HelixQL feature on one page. Each entry shows what it does, its syntax variants, and links to the full documentation.
Query Structure
QUERY
Define a named query with typed parameters.
QUERY GetUser(user_id: ID) =>
QUERY CreateUser(name: String, age: U8) =>
QUERY GetAllUsers() =>
- A query with one typed parameter.
- A query with multiple typed parameters.
- A query with no parameters.
See What is HelixQL? for more details.
RETURN
Specify query output values.
RETURN users
RETURN user, posts
RETURN users::{name, age}
RETURN users::ID
RETURN "ok"
RETURN NONE
- Return a single binding.
- Return multiple bindings.
- Return projected fields.
- Return only IDs.
- Return a string literal.
- Return no payload.
See Output Values for more details.
<- (Assignment)
Bind the result of an expression to a variable.
user <- N<User>(user_id)
users <- N<User>::WHERE(_::{age}::GT(18))
count <- N<User>::COUNT
- Bind a node lookup to
user. - Bind a filtered traversal to
users. - Bind a count result to
count.
See What is HelixQL? for more details.
Comments (//)
Single-line comments.
// This is a comment
user <- N<User>(user_id) // inline comment
- A standalone comment line.
- A comment at the end of a statement.
See What is HelixQL? for more details.
Types
Scalar Types
Built-in primitive types for schema fields and query parameters.
name: String
is_active: Boolean
age: U8
count: I64
score: F64
- Text data.
- True/false value.
- 8-bit unsigned integer. Also available:
U16,U32,U64,U128. - 64-bit signed integer. Also available:
I8,I16,I32. - 64-bit floating point. Also available:
F32.
See Helix Types for more details.
ID
UUID identifier type for nodes, edges, and vectors.
QUERY GetUser(user_id: ID) =>
user <- N<User>(user_id)
RETURN user::{userID: ID}
- Accept an ID as a query parameter.
- Access an element’s unique identifier in a property selection.
See Helix Types for more details.
Date
Timestamp / RFC3339 date type.
created_at: Date
created_at: Date DEFAULT NOW
- A date field in a schema.
- A date field with automatic timestamp default.
See Helix Types for more details.
[T] (Arrays)
Array of any type.
QUERY Search(vector: [F64]) =>
QUERY CreateUsers(user_data: [{name: String, age: U8}]) =>
tags: [String]
- An array of 64-bit floats as a parameter.
- An array of objects as a parameter.
- An array of strings as a schema field.
See Helix Types for more details.
Schema Definition
N:: (Node Schema)
Define node types with properties.
N::User {
name: String,
age: U8,
email: String,
}
- Define a
Usernode type with three properties.
See Schema Definition for more details.
E:: (Edge Schema)
Define edge types with source, target, and optional properties.
E::Follows {
From: User,
To: User,
}
E::Friends {
From: User,
To: User,
Properties: {
since: Date,
strength: F64
}
}
- An edge with no properties connecting
UsertoUser. - An edge with properties connecting
UsertoUser.
See Schema Definition for more details.
V:: (Vector Schema)
Define vector embedding types with metadata properties.
V::Document {
content: String,
created_at: Date
}
V::Embedding {}
- A vector type with metadata properties.
- A vector type with no extra properties.
See Schema Definition for more details.
INDEX
Create indexed fields for fast property-based lookup.
N::User {
INDEX email: String,
name: String,
}
- Index the
emailfield onUsernodes for fast lookups viaN<User>({email: email}).
See Secondary Indexing for more details.
UNIQUE INDEX
Create unique constraints on fields, preventing duplicates.
N::User {
UNIQUE INDEX email: String,
name: String,
}
E::BestFriend UNIQUE {
From: User,
To: User,
}
- Enforce uniqueness on the
emailfield. - Enforce that only one
BestFriendedge can exist from a given user.
See Unique Indexes for more details.
DEFAULT
Set default property values used when a value is not provided on insert.
N::Post {
title: String,
view_count: I32 DEFAULT 0,
status: String DEFAULT "draft",
created_at: Date DEFAULT NOW,
is_published: Boolean DEFAULT false,
archived_at: Date DEFAULT NONE,
}
- A schema with defaults for numbers, strings, timestamps, booleans, and NONE.
See Default Values for more details.
Node Operations
AddN
Create new nodes with optional properties.
AddN<User>
AddN<User>({name: "Alice", age: 25, email: "alice@example.com"})
- Create a
Usernode with no properties. - Create a
Usernode with a properties object.
See Create Nodes for more details.
N
Select nodes by type, by ID, or by indexed property.
N<User>
N<User>(user_id)
N<User>({email: email})
- Select all
Usernodes. - Select a
Userby ID. - Select a
Userby an indexed property value.
See Select Nodes for more details.
UpsertN
Insert-or-update a node. Updates existing nodes from the traversal context, or creates a new one if none are found.
existing <- N<Person>::WHERE(_::{name}::EQ(name))
person <- existing::UpsertN({name: "Alice", age: 30})
- Find existing nodes matching a condition.
- Upsert with the given properties — updates if found, creates if not.
See Upsert Nodes for more details.
Edge Operations
AddE
Create edges between nodes with optional properties.
AddE<Follows>::From(user1_id)::To(user2_id)
AddE<Friends>({since: "2024-01-15", strength: 0.85})::From(user1_id)::To(user2_id)
- Create a
Followsedge between two nodes. - Create a
Friendsedge with properties.
See Create Edges for more details.
E
Select edges by type or by ID.
E<Follows>
E<Follows>(edge_id)
- Select all
Followsedges. - Select a specific
Followsedge by ID.
See Select Edges for more details.
UpsertE
Insert-or-update an edge. Operates on an existing edge traversal context — updates if an edge exists between the specified nodes, creates a new one otherwise.
existing <- E<Knows>
edge <- existing::UpsertE({since: "2024-06-01"})::From(user1_id)::To(user2_id)
- Select the edge type to operate on.
- Upsert with properties between two nodes — updates if found, creates if not.
See Upsert Edges for more details.
Vector Operations
AddV
Create vector embeddings with optional properties.
AddV<Document>(vector)
AddV<Document>(vector, {content: "Hello world", created_at: created_at})
AddV<Document>(Embed(content), {content: content})
- Create a vector with no metadata.
- Create a vector with metadata properties.
- Create a vector using the built-in
Embedfunction.
See Create Vectors for more details.
V
Select vectors by type or by ID.
V<Document>
V<Document>(vector_id)
- Select all
Documentvectors. - Select a specific vector by ID.
See Select Vectors for more details.
UpsertV
Insert-or-update a vector. Updates existing vectors from the traversal context, or creates a new one if none are found.
existing <- V<Document>::WHERE(_::{content}::EQ(content))
doc <- existing::UpsertV(Embed(content), {content: content})
- Find existing vectors matching a condition.
- Upsert with new vector data and properties.
See Upsert Vectors for more details.
Embed
Generate vector embeddings from text using your configured embedding model.
AddV<Document>(Embed(content), {content: content})
SearchV<Document>(Embed(query), 10)
- Embed text and store it as a vector.
- Embed a search query for vector similarity search.
See Embedding Vectors for more details.
Traversal Steps (from Nodes)
::Out
Follow outgoing edges and return the target nodes.
N<User>(user_id)::Out<Follows>
N<User>(user_id)::Out<Follows>::Out<Follows>
- Get all users that
user_idfollows. - Chain traversals to get followers-of-followers.
See Traversals From Nodes for more details.
::In
Follow incoming edges and return the source nodes.
N<User>(user_id)::In<Follows>
- Get all users that follow
user_id.
See Traversals From Nodes for more details.
::OutE
Return the outgoing edges themselves (with their properties).
N<User>(user_id)::OutE<Follows>
- Get the outgoing
Followsedge objects from a user.
See Traversals From Nodes for more details.
::InE
Return the incoming edges themselves (with their properties).
N<User>(user_id)::InE<Follows>
- Get the incoming
Followsedge objects pointing at a user.
See Traversals From Nodes for more details.
Traversal Steps (from Edges)
::FromN
Get the source node of an edge.
E<Creates>(edge_id)::FromN
- Get the node that the
Createsedge originates from.
See Traversals From Edges for more details.
::ToN
Get the target node of an edge.
E<Creates>(edge_id)::ToN
- Get the node that the
Createsedge points to.
See Traversals From Edges for more details.
::FromV
Get the source vector of an edge.
E<HasEmbedding>(edge_id)::FromV
- Get the vector that the edge originates from.
See Traversals From Edges for more details.
::ToV
Get the target vector of an edge.
E<HasEmbedding>(edge_id)::ToV
- Get the vector that the edge points to.
See Traversals From Edges for more details.
Filtering & Conditions
::WHERE
Filter elements by a condition.
N<User>::WHERE(_::{age}::GT(18))
N<User>::WHERE(EXISTS(_::In<Follows>))
N<User>::WHERE(AND(_::{age}::GT(18), _::{age}::LT(30)))
- Filter users where
ageis greater than 18. - Filter users that have at least one follower.
- Combine multiple conditions with
AND.
See Conditional Steps for more details.
::INTERSECT
Keep only elements that appear in a sub-traversal result for every upstream element.
N<Tag>::WHERE(_::{name}::IS_IN(tag_names))::INTERSECT(_::In<HasTag>)
N<Tag>::WHERE(_::{name}::IS_IN(tag_names))::INTERSECT(_::In<HasTag>)::WHERE(_::{title}::EQ(title))
INTERSECTtakes an anonymous traversal expression, such as_::In<HasTag>.- Helix runs that sub-traversal for each upstream element, then keeps only IDs shared across all sub-results.
- If the upstream set is empty (or there is no overlap), the final result is empty.
See Traversals From Nodes for more details.
::EQ
Equals comparison. Works with strings, booleans, and numbers.
::WHERE(_::{status}::EQ("active"))
::WHERE(_::{name}::EQ(name))
- Filter where
statusequals the string"active". - Filter where
nameequals a query parameter.
See Conditional Steps for more details.
::NEQ
Not equals comparison. Works with strings, booleans, and numbers.
::WHERE(_::{role}::NEQ("admin"))
- Filter where
roleis not"admin".
See Conditional Steps for more details.
::GT
Greater than comparison. Works with numbers.
::WHERE(_::{age}::GT(18))
- Filter where
ageis greater than 18.
See Conditional Steps for more details.
::GTE
Greater than or equal comparison. Works with numbers.
::WHERE(_::{rating}::GTE(4.5))
- Filter where
ratingis at least 4.5.
See Conditional Steps for more details.
::LT
Less than comparison. Works with numbers.
::WHERE(_::{age}::LT(30))
- Filter where
ageis less than 30.
See Conditional Steps for more details.
::LTE
Less than or equal comparison. Works with numbers.
::WHERE(_::{priority}::LTE(2))
- Filter where
priorityis at most 2.
See Conditional Steps for more details.
::CONTAINS
Check if a string contains a substring or an array contains an element.
::WHERE(_::{name}::CONTAINS("john"))
::WHERE(_::Out<Follows>::CONTAINS(user))
- Filter where
namecontains the substring"john". - Filter where the outgoing
Followsset containsuser.
See Conditional Steps for more details.
::IS_IN
Check if a value exists in an array.
::WHERE(_::{status}::IS_IN(["active", "pending"]))
- Filter where
statusis one of"active"or"pending".
See Conditional Steps for more details.
EXISTS
Check if a traversal returns any results.
::WHERE(EXISTS(_::In<Follows>))
::WHERE(!EXISTS(_::In<Follows>))
- Filter for elements that have incoming
Followsedges. - Filter for elements that have no incoming
Followsedges (negated with!).
See Conditional Steps for more details.
Multiple Conditions (AND / OR / !)
Combine conditions with boolean logic.
::WHERE(AND(_::{age}::GT(18), _::{age}::LT(30)))
::WHERE(OR(_::{role}::EQ("admin"), _::{role}::EQ("moderator")))
::WHERE(!AND(_::{is_active}::EQ(true), _::{age}::GT(18)))
- Match when all conditions are true.
- Match when any condition is true.
- Negate an
AND/ORblock by prefixing!.
See Multiple Conditional Steps for more details.
Result Operations
::FIRST
Get the first element from a traversal result.
N<User>::FIRST
N<User>(user_id)::In<Follows>::FIRST
- Get the first
Usernode. - Get the first follower of a user.
See Result Operations for more details.
::COUNT
Count the number of elements in a traversal result.
N<User>::COUNT
N<User>(user_id)::In<Follows>::COUNT
- Count all
Usernodes. - Count how many users follow
user_id.
See Result Operations for more details.
::RANGE
Get a range of elements (inclusive start, exclusive end).
N<User>::RANGE(0, 10)
N<User>::RANGE(start, end)
- Get the first 10 users (elements 0 through 9).
- Get a dynamic page of users using parameters.
See Result Operations for more details.
::ORDER
Sort elements ascending or descending by a property.
N<User>::ORDER<Desc>(_::{age})
N<User>::ORDER<Asc>(_::{age})
- Sort users by
agedescending (oldest first). - Sort users by
ageascending (youngest first).
See Result Operations for more details.
Aggregation
::GROUP_BY
Group elements by one or more properties, returning count summaries.
N<User>::GROUP_BY(age)
N<User>::GROUP_BY(department, role)
- Group users by
age, returning[{age: 25, count: 3}, ...]. - Group users by multiple properties.
See Group By for more details.
::AGGREGATE_BY
Group elements by properties, returning counts and full data objects.
N<User>::AGGREGATE_BY(department)
N<User>::AGGREGATE_BY(department, role)
- Aggregate users by
department, returning counts and full user objects per group. - Aggregate by multiple properties.
See Aggregations for more details.
Property Operations
::{} (Property Selection)
Select specific properties from elements.
users::{name, age}
users::{name, age, email}
- Return only
nameandagefrom each user. - Return three specific fields.
See Property Access for more details.
::ID
Access an element’s unique identifier.
users::ID
users::{userID: ID, name}
- Return only the IDs of users.
- Map the ID to a custom field name alongside other properties.
See Property Access for more details.
::!{} (Property Exclusion)
Exclude specific properties, returning all others.
users::!{email, location}
- Return all user properties except
emailandlocation.
See Property Exclusion for more details.
Property Remapping
Rename properties in output using alias syntax.
users::{displayName: name, userAge: age}
users::{userID: ID, displayName: name}
- Rename
nametodisplayNameandagetouserAge. - Map the ID to
userIDandnametodisplayName.
See Property Remappings for more details.
Spread Operator (..)
Include all properties while optionally adding or remapping specific fields.
users::{
userID: ID,
..
}
- Include all schema properties plus a computed
userIDfield.
See Property Access for more details.
Nested Mappings (::|name|{})
Closure-style scoped property access for complex output structures.
user::|usr|{
posts: posts::{
postID: ID,
creatorID: usr::ID,
creatorName: usr::name,
..
}
}
- Scope
usras a reference touser, then use it inside nested property selections.
See Property Remappings for more details.
Computed Properties
Add derived values to output using traversals or expressions.
users::{
userID: ID,
followerCount: _::In<Follows>::COUNT
}
- Add a
followerCountcomputed from the incomingFollowsedge count.
See Property Additions for more details.
Modification Operations
::UPDATE
Update properties on existing elements.
N<Person>(user_id)::UPDATE({name: "Alice Johnson", age: 26})
- Update the
nameandageof a person. Omitted properties stay unchanged.
See Updating Items for more details.
DROP
Delete elements and their related edges.
DROP N<User>(user_id)
DROP N<User>(user_id)::Out<Follows>
DROP N<User>(user_id)::OutE<Follows>
- Delete a user node and all its connected edges.
- Delete all nodes that the user follows (and connecting edges).
- Delete only the outgoing
Followsedges without touching neighbor nodes.
See Delete Operation for more details.
Search
SearchV
Vector similarity search using cosine similarity.
SearchV<Document>(vector, 10)
SearchV<Document>(Embed(query), limit)
- Search for the 10 most similar
Documentvectors to a raw vector. - Search using an embedded text query with a dynamic limit.
See Vector Search for more details.
SearchBM25
Keyword search using the BM25 ranking algorithm.
SearchBM25<Document>(keywords, 10)
SearchBM25<Document>(query, limit)
- Search
Documentnodes for keywords, returning up to 10 results. - Search with dynamic query text and limit.
See Keyword Search for more details.
Reranking
::RerankRRF
Reciprocal Rank Fusion — combine multiple ranked lists without score calibration.
::RerankRRF
::RerankRRF(k: 60.0)
- Apply RRF with the default
k=60. - Apply RRF with a custom
kparameter.
See RerankRRF for more details.
::RerankMMR
Maximal Marginal Relevance — diversify results by balancing relevance with diversity.
::RerankMMR(lambda: 0.7)
::RerankMMR(lambda: 0.5, distance: "euclidean")
::RerankMMR(lambda: 0.6, distance: "dotproduct")
- Apply MMR with cosine distance (default).
- Apply MMR with euclidean distance.
- Apply MMR with dot product distance.
See RerankMMR for more details.
Shortest Path Algorithms
::ShortestPath
Default shortest path (BFS). Minimizes hop count when no weights are provided.
N<City>(start_id)::ShortestPath<Road>::To(end_id)
- Find the shortest unweighted path via
Roadedges.
See Shortest Path Algorithms for more details.
::ShortestPathBFS
Unweighted shortest path using breadth-first search. Minimizes the number of hops.
N<City>(start_id)::ShortestPathBFS<Road>::To(end_id)
- Find the shortest unweighted path from one city to another via
Roadedges.
See ShortestPathBFS for more details.
::ShortestPathDijkstras
Weighted shortest path using Dijkstra’s algorithm.
N<City>(start_id)::ShortestPathDijkstras<Road>(_::{distance})::To(end_id)
- Find the shortest weighted path using the
distanceedge property as the weight.
See ShortestPathDijkstras for more details.
::ShortestPathAStar
Heuristic shortest path using the A* algorithm.
N<City>(start_id)::ShortestPathAStar<Road>(_::{distance}, "heuristic")::To(end_id)
- Find the shortest path using edge
distanceas weight and a nodeheuristicproperty for guidance.
See ShortestPathAStar for more details.
Custom Weight Expressions
Define edge weights for path algorithms using property contexts.
_::{distance}
_::FromN::{population}
_::ToN::{capacity}
ADD(_::{distance}, _::ToN::{traffic})
- Use an edge property as weight.
- Reference the source node’s property.
- Reference the target node’s property.
- Combine edge and node properties with arithmetic.
See Custom Weight Calculations for more details.
Control Flow
FOR ... IN
Iterate over collections and perform operations on each element.
FOR user_name IN user_names {
AddN<User>({name: user_name})
}
- Loop through a collection of names and create a node for each element.
See FOR Loops for more details.
FOR with Destructuring
Unpack properties directly in the loop variable declaration.
FOR {name, age, email} IN user_data {
AddN<User>({name: name, age: age, email: email})
}
- Destructure
name,age, andemailfrom each element and use them directly.
See FOR Loop Destructuring for more details.
Math Functions
Arithmetic
Basic arithmetic operations.
ADD(price, tax)
SUB(total, discount)
MUL(quantity, unit_price)
DIV(total, count)
POW(base, exponent)
MOD(value, divisor)
- Addition:
price + tax. - Subtraction:
total - discount. - Multiplication:
quantity * unit_price. - Division:
total / count. - Power:
base ^ exponent. - Modulo:
value % divisor.
See Arithmetic Functions for more details.
Unary Math
Single-argument mathematical functions.
ABS(value)
SQRT(value)
LN(value)
LOG10(value)
LOG(value, base)
EXP(value)
CEIL(value)
FLOOR(value)
ROUND(value)
- Absolute value.
- Square root.
- Natural logarithm.
- Base-10 logarithm.
- Logarithm with custom base.
- Exponential (
e^value). - Round up to nearest integer.
- Round down to nearest integer.
- Round to nearest integer.
See Unary Math Functions for more details.
Trigonometry
Trigonometric and inverse trigonometric functions (angles in radians).
SIN(angle)
COS(angle)
TAN(angle)
ASIN(value)
ACOS(value)
ATAN(value)
ATAN2(y, x)
- Sine of an angle.
- Cosine of an angle.
- Tangent of an angle.
- Inverse sine (arc sine).
- Inverse cosine (arc cosine).
- Inverse tangent (arc tangent).
- Two-argument inverse tangent.
See Trigonometric Functions for more details.
Constants
Mathematical constants.
PI()
E()
- Returns the value of pi (~3.14159).
- Returns the value of Euler’s number (~2.71828).
See Mathematical Constants for more details.
Aggregate Functions
Aggregate operations on collections.
MIN(ages)
MAX(ages)
SUM(prices)
AVG(scores)
COUNT(users)
- Minimum value in a collection.
- Maximum value in a collection.
- Sum of all values.
- Average of all values.
- Number of elements.
See Aggregate Functions for more details.
Macros
#[model]
Specify which embedding model to use for Embed() calls within a query.
#[model("gemini:gemini-embedding-001:RETRIEVAL_DOCUMENT")]
QUERY StoreDocument(content: String) =>
doc <- AddV<Document>(Embed(content), {content: content})
RETURN doc
- Override the default embedding model for this query using the
#[model]macro.
See Model Macro for more details.
#[mcp]
Expose a query as an MCP (Model Context Protocol) endpoint for AI agents.
#[mcp]
QUERY GetDocument(doc_id: ID) =>
doc <- N<Document>(doc_id)
RETURN doc
- Mark a query as an MCP tool, making it accessible to LLM applications.
See MCP Macro for more details.
Output
Output Values
Return literals, computed values, and structured objects from queries.
RETURN "Success"
RETURN users::{name, age}
RETURN user, posts
RETURN users::!{email}
RETURN NONE
- Return a string literal.
- Return projected properties.
- Return multiple bindings.
- Return all properties except
email. - Return no payload.
See Output Values for more details.