helix-query-from-gremlin
Gremlin To Helix Queries
Translate Gremlin into Helix Rust DSL by turning imperative step chains into explicit anchors, traversals, predicates, and result shaping.
When To Use
Use this skill when the task is to:
- translate a Gremlin traversal into Helix Rust DSL
- port a TinkerPop query into a stored Helix route
- replace
g.V,hasLabel,has,out,in,both,outE,inE,repeat,emit,dedup,count,range, orlimitwith Helix DSL equivalents - explain how a Gremlin traversal should be expressed in Helix Rust
Do not use this skill as the main guide for Cypher, SQL, or dynamic inline-query JSON.
First Steps
Before translating:
- Inspect the local repo for real labels, edge labels, property names, and route style.
- Parse the Gremlin traversal into its start step, filters, directional steps, repeat logic, and result shaping.
- Decide whether the target route is read or write.
- Identify any Gremlin constructs that are not a direct one-to-one translation.
If the local repo does not already contain an obvious Helix pattern, use:
docs/gremlin-rosetta.mddocs/dsl-cheatsheet.mdexamples/authoring-patterns.mdexamples/search-patterns.md
Translation Workflow
1. Choose The Start Step Carefully
Translate the first Gremlin step into the narrowest Helix anchor you can justify.
Prefer:
- node ID or edge ID
- unique property lookup
- equality-indexed property lookup
- scoped label scan
- broad label scan
Do not keep a broad g.V() or g.E() shape if the traversal can start narrower.
2. Translate Each Directional Step Explicitly
Typical mappings:
.out("REL")to.out(Some("REL")).in("REL")to.in_(Some("REL")).both("REL")to.both(Some("REL")).outE("REL")to.out_e(Some("REL")).inE("REL")to.in_e(Some("REL"))
3. Translate hasLabel And has Into Label And Predicate Logic
Typical mappings:
hasLabel("User")ton_with_label("User")has("status", status)towhere_(Predicate::eq_param("status", "status"))has("status", within(statuses))towhere_(Predicate::is_in_param("status", "statuses"))
4. Translate Result-Shaping Steps Deliberately
Use:
dedup()for Gremlindedup()count()for Gremlincount()order_byororder_by_multiplefor Gremlin orderinglimit,skip, andrangefor result-window controlproject(...)orvalue_map(...)for output shape
5. Treat Complex Gremlin Features As Semantic Translations
Do not force literal translations for:
path()select(...)project(...)in Gremlin's map-building sensecoalesce(...)choose(...)union(...)group()andgroupCount()sideEffect(...)sack(...)- open-ended repeat logic
Translate them semantically instead.
Key Gremlin Rules
g.V And g.E
Use the narrowest anchor possible. For bare g.E(), prefer rewriting to a node-anchored edge traversal or an edge-ID anchor rather than an all-edge scan.
valueMap And values
Gremlin often emits map or scalar streams. Helix service routes usually work better with explicit object-shaped projections.
Use value_map(...) when a property map is acceptable, and use project(...) when the route should return a stable shape.
repeat And emit
Use bounded repeat(...) with an explicit .times(...) limit. Do not assume arbitrary unbounded traversal semantics.
Canonical Example
Gremlin:
g.V().hasLabel('User').has('userId', userId).out('FOLLOWS').has('status', status).order().by('createdAt', desc).limit(limit).valueMap('userId', 'name', 'status', 'createdAt')
Helix Rust DSL:
read_batch()
.var_as(
"user",
g().n_with_label("User")
.where_(Predicate::eq_param("userId", "userId")),
)
.var_as(
"results",
g().n(NodeRef::var("user"))
.out(Some("FOLLOWS"))
.where_(Predicate::eq_param("status", "status"))
.order_by("createdAt", Order::Desc)
.limit(Expr::param("limit"))
.value_map(Some(vec!["userId", "name", "status", "createdAt"])),
)
.returning(["results"])
Anti-Patterns
Do not:
- translate Gremlin step chains by string substitution alone
- preserve a broad
g.V()org.E()when a narrower anchor exists - ignore edge direction
- assume
valueMap,path,select, orprojecthas a one-step literal Helix equivalent - translate open-ended repeat logic without setting an explicit bound
- invent labels, properties, or edge names instead of reading the target schema
Validation Checklist
Before finishing:
- verify the start step became the narrowest practical Helix anchor
- verify edge directions are translated correctly
- verify
hasLabelandhasbecame explicit label and predicate logic - verify
dedup,count,limit,range, and ordering were mapped deliberately - verify
valueMaporvaluesbecame an intentional Helix output shape - verify
repeatwas translated with an explicit bound - verify complex Gremlin features were translated semantically, not literally
- verify labels, edge labels, and properties match the local repo exactly
Repo References
For shared references in this repo, see:
docs/gremlin-rosetta.mddocs/dsl-cheatsheet.mdexamples/authoring-patterns.mdexamples/search-patterns.md
More from helixdb/skills
helix-query-json-dynamic
Build and validate HelixDB dynamic inline-query requests for POST /v1/query. Use when the task involves dynamic queries, inline query JSON, the inline AST (steps, predicates, expressions, projections), parameter_types, DateTime coercion, query warming, or debugging a request body sent directly to the Helix gateway. See REFERENCE.md for every AST variant and EXAMPLES.md for copy-pasteable payloads.
10helix-query-authoring
Write and revise HelixDB Rust DSL stored queries from scratch. Use when the task is to add, update, or review a Helix query built with read_batch, write_batch, traversal builders, projections, indexes, BM25 text search, or vector search. Inspect local labels, edges, properties, and existing query patterns before inventing new code. See REFERENCE.md for the full builder catalog and EXAMPLES.md for end-to-end patterns.
10helix-query-optimize
Review and improve HelixDB query performance and query shape. Use when the task is to optimize a slow Helix query, improve anchor choice, tighten index usage, reduce traversal breadth, slim projections, fix BM25 or vector search scope, or decide between stored and dynamic routes.
8helix-query-from-cypher
Translate Cypher and Neo4j-style queries into HelixDB Rust DSL stored queries. Use when the input contains Cypher, Neo4j, MATCH, OPTIONAL MATCH, WHERE, RETURN, ORDER BY, LIMIT, DISTINCT, MERGE, CASE, UNWIND, FOREACH, DETACH DELETE, IS NULL, or variable-length path patterns and the goal is to produce an equivalent Helix Rust query.
7