helix-query-json-dynamic
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHelix Dynamic Query JSON
Helix 动态查询 JSON
Use this skill for inline dynamic query requests sent directly to .
POST /v1/queryThe inline body is a JSON serialization of the Rust DSL AST. Every variant an agent can send is documented in the companion files. If you are writing anything beyond a trivial read, open first — do not guess variant names or field shapes.
queryREFERENCE.md本技能适用于直接发送至的内联动态查询请求。
POST /v1/query内联请求体是Rust DSL AST的JSON序列化形式。Agent可发送的所有变体均记录在配套文件中。如果您要编写的查询超出简单读取范畴,请先打开——请勿猜测变体名称或字段结构。
queryREFERENCE.mdReference Files
参考文件
- — complete AST variant catalog (every
REFERENCE.md,Step,Predicate,Expr,PropertyValue,IndexSpec,RepeatConfig, envelope field). Use when writing a non-trivial request.BatchCondition - — working end-to-end JSON bodies: reads, writes, vector/text search,
EXAMPLES.md,Repeat,Choose,Coalesce, aggregations, upserts,Union, index management, warming. Copy the closest scenario as a starting point.ForEach
- — 完整的AST变体目录(包含所有
REFERENCE.md、Step、Predicate、Expr、PropertyValue、IndexSpec、RepeatConfig及信封字段)。编写非简单请求时使用。BatchCondition - — 可直接运行的端到端JSON请求体:读取、写入、向量/文本搜索、
EXAMPLES.md、Repeat、Choose、Coalesce、聚合、更新插入、Union、索引管理、预热。复制最接近场景的示例作为起点。ForEach
When To Use
使用场景
Use this skill when the task is to:
- build a dynamic Helix request body
- debug a failing call
POST /v1/query - add to a dynamic request
parameter_types - send or typed-array parameters correctly
DateTime - understand read versus write behavior on the dynamic route
- use query warming on a dynamic read
- translate a Rust DSL query you already have into its JSON form
Do not use this skill as the main guide for writing stored Rust DSL query functions. Use for that.
helix-query-authoring当您需要完成以下任务时,可使用本技能:
- 构建Helix动态请求体
- 调试失败的调用
POST /v1/query - 为动态请求添加
parameter_types - 正确发送或类型化数组参数
DateTime - 理解动态路由的读取与写入行为差异
- 为动态读取请求启用查询预热
- 将已有的Rust DSL查询转换为JSON形式
请勿将本技能作为编写存储式Rust DSL查询函数的主要指南,此类场景请使用。
helix-query-authoringFirst Steps
前期步骤
Before writing the payload:
- Decide whether this should really be a stored route instead of a dynamic route. If the request is part of steady-state application traffic, prefer a stored route.
- Confirm whether the request is a read or a write. A query that contains any mutation step (,
AddN,AddE,SetProperty,RemoveProperty,Drop,DropEdge,DropEdgeLabeled, or anyDropEdgeById/Create*Index) must useDropIndex.request_type: "write" - Confirm whether the inline object already exists in code, a test, or a serialized payload — prefer copying a known-good shape.
query - Identify any parameters that need explicit typing, especially and typed arrays.
DateTime
编写请求负载前,请完成以下操作:
- 判断该请求是否更适合存储式路由而非动态路由。如果请求属于稳态应用流量,优先选择存储式路由。
- 确认请求类型为读取或写入。包含任何突变步骤(、
AddN、AddE、SetProperty、RemoveProperty、Drop、DropEdge、DropEdgeLabeled,或任何DropEdgeById/Create*Index)的查询必须设置DropIndex。request_type: "write" - 确认内联对象是否已存在于代码、测试用例或序列化负载中——优先复制已知可用的结构。
query - 识别需要显式类型声明的参数,尤其是和类型化数组。
DateTime
Required Envelope Rules
信封字段规则
- send requests to
POST /v1/query - must be
request_typeor"read"(lowercase — the enum uses"write")#[serde(rename_all = "lowercase")] - must be a single inline route object (a
queryorReadBatch), not the fullWriteBatchbundlequeries.json - is optional
parameters - is optional until you need schema-aware coercion (see Parameter Typing)
parameter_types - is an optional request header, valid only for reads
X-Helix-Warm: true
- 请求发送至
POST /v1/query - 必须为
request_type或"read"(小写——枚举使用"write")#[serde(rename_all = "lowercase")] - 必须是单个内联路由对象(
query或ReadBatch),不能是完整的WriteBatch包queries.json - 为可选字段
parameters - 为可选字段,仅当需要基于Schema的类型转换时使用(请参阅参数类型部分)
parameter_types - 是可选请求头,仅对读取请求有效
X-Helix-Warm: true
Canonical Request Shape
标准请求结构
json
{
"request_type": "read",
"query": {
"queries": [
{
"Query": {
"name": "node_exists",
"steps": ["Count"],
"condition": null
}
}
],
"returns": ["node_exists"]
},
"parameters": {
"name": "Alice",
"entity_id": 123
},
"parameter_types": {
"name": "String",
"entity_id": "I64"
}
}Notes on the shape:
- contains a
query(orReadBatch); both haveWriteBatch.{ "queries": [...], "returns": [...] } - Each element of is a
queries— eitherBatchEntryor{"Query": {...}}.{"ForEach": {...}} - is a valid step list:
"steps": ["Count"]is a unit variant so it serializes as a bare string. Data-carrying variants are wrapped:Count,{"Limit": 10}, etc.{"Has": ["name", {"String": "Alice"}]}
json
{
"request_type": "read",
"query": {
"queries": [
{
"Query": {
"name": "node_exists",
"steps": ["Count"],
"condition": null
}
}
],
"returns": ["node_exists"]
},
"parameters": {
"name": "Alice",
"entity_id": 123
},
"parameter_types": {
"name": "String",
"entity_id": "I64"
}
}结构说明:
- 包含
query(或ReadBatch);两者均包含WriteBatch。{ "queries": [...], "returns": [...] } - 中的每个元素都是
queries——格式为BatchEntry或{"Query": {...}}。{"ForEach": {...}} - 是有效的步骤列表:
"steps": ["Count"]是单元变体,因此序列化为纯字符串。携带数据的变体需要包裹:Count、{"Limit": 10}等。{"Has": ["name", {"String": "Alice"}]}
Serde Encoding Rules
Serde编码规则
Every encoding in follows these rules. Internalize them or the request will fail with / errors.
REFERENCE.mdunknown variantinvalid type-
Default encoding is externally tagged. Given a Rust enumwithout a
E::Var(..)attribute:#[serde(...)]- Unit variant (no data): bare string. →
Step::Count."Count"is a tuple-with-data variant, not unit — see rule 2.Predicate::HasKey - Tuple variant with 1 field: .
{"Var": <inner>}→Step::N(NodeRef::Ids(vec![644])).{"N": {"Ids": [644]}} - Tuple variant with 2+ fields: .
{"Var": [a, b, ...]}→Predicate::Eq("status", PropertyValue::String("active")).{"Eq": ["status", {"String": "active"}]}→Predicate::Between("score", 60, 100).{"Between": ["score", {"I64": 60}, {"I64": 100}]} - Struct variant: .
{"Var": {"field": ...}}→Step::VectorSearchNodes { label, property, ... }.{"VectorSearchNodes": {"label": "...", "property": "...", ...}}
- Unit variant (no data): bare string.
-
Three enums are— no variant wrapper:
#[serde(untagged)]- (the value of the envelope's
BatchQueryfield): write thequery/ReadBatchobject inline. There is noWriteBatchwrapper.{"Read": ...} - (element of a
Projectionstep's list): write the inner struct directly.Project→PropertyProjection.{"source": "name", "alias": "name"}→ExprProjection. Do not write{"alias": "age_plus_one", "expr": {...}}or{"Property": {...}}wrappers.{"Expr": {...}} - (values inside the top-level
DynamicQueryValuemap): bare JSON.parameters,"limit": 25,"tags": ["a","b"]. No"user": {"name": "Alice"}wrapping here — that form is{"I64": 25}, which is inside the AST, not at parameter-value position.PropertyValue
-
is
DynamicQueryRequestType: userename_all = "lowercase"/"read", never"write"/"Read"."Write" -
Optional fields may be omitted or set to.
null,tenant_value,condition,else_traversal, and similar all serialize viaemit_predicatewhen unset, but the server accepts explicitskip_serializing_if = "Option::is_none".null -
is distinct from
PropertyValue. Inside the AST (literals inDynamicQueryValue,Has,Eqproperties wrapped inAddN, etc.) values are tagged:PropertyInput::Value,{"String": "..."},{"I64": 42},{"Bool": true},{"F64": 3.14},{"F64Array": [0.1, 0.2]}is wrong — use the bare string{"Null": null}for the unit variant. At parameter-value position (top-level"Null"map) values are untagged bare JSON.parameters -
over JSON: supply an RFC3339 string or epoch-millis integer as the parameter value, and declare
DateTime. No implicit coercion — a plain string parameter without the type declaration is just a string.parameter_types: {"p": "DateTime"} -
is not round-trippable. The builder raises
Bytes. Do not sendUnsupportedBytesParameterparameters through the JSON dynamic route.Bytes
REFERENCE.mdunknown variantinvalid type-
默认编码为外部标签式。对于未添加属性的Rust枚举
#[serde(...)]:E::Var(..)- 单元变体(无数据):纯字符串。→
Step::Count。"Count"是带数据的元组变体,不属于单元变体——请参阅规则2。Predicate::HasKey - 带1个字段的元组变体:。
{"Var": <inner>}→Step::N(NodeRef::Ids(vec![644]))。{"N": {"Ids": [644]}} - 带2个及以上字段的元组变体:。
{"Var": [a, b, ...]}→Predicate::Eq("status", PropertyValue::String("active"))。{"Eq": ["status", {"String": "active"}]}→Predicate::Between("score", 60, 100)。{"Between": ["score", {"I64": 60}, {"I64": 100}]} - 结构体变体:。
{"Var": {"field": ...}}→Step::VectorSearchNodes { label, property, ... }。{"VectorSearchNodes": {"label": "...", "property": "...", ...}}
- 单元变体(无数据):纯字符串。
-
三个枚举采用——无变体包裹:
#[serde(untagged)]- (信封
BatchQuery字段的值):直接内联写入query/ReadBatch对象。不需要WriteBatch包裹。{"Read": ...} - (
Projection步骤列表中的元素):直接写入内部结构体。Project→PropertyProjection。{"source": "name", "alias": "name"}→ExprProjection。请勿写入{"alias": "age_plus_one", "expr": {...}}或{"Property": {...}}包裹。{"Expr": {...}} - (顶层
DynamicQueryValue映射中的值):纯JSON。parameters、"limit": 25、"tags": ["a","b"]。此处不需要"user": {"name": "Alice"}包裹——该格式是{"I64": 25},用于AST内部,而非参数值位置。PropertyValue
-
采用
DynamicQueryRequestType:使用rename_all = "lowercase"/"read",切勿使用"write"/"Read"。"Write" -
可选字段可省略或设为。
null、tenant_value、condition、else_traversal及类似字段在未设置时通过emit_predicate序列化,但服务器也接受显式的skip_serializing_if = "Option::is_none"。null -
与
PropertyValue不同。AST内部(DynamicQueryValue、Has中的字面量,Eq属性中包裹在AddN中的值等)的值是带标签的:PropertyInput::Value、{"String": "..."}、{"I64": 42}、{"Bool": true}、{"F64": 3.14};单元变体{"F64Array": [0.1, 0.2]}需使用纯字符串Null,而非"Null"。在参数值位置(顶层{"Null": null}映射)的值是无标签的纯JSON。parameters -
JSON中的:参数值可提供RFC3339字符串或时间戳毫秒整数,并声明
DateTime。无隐式类型转换——未声明类型的纯字符串参数仅会被视为普通字符串。parameter_types: {"p": "DateTime"} -
类型不支持往返序列化。构建器会抛出
Bytes错误。请勿通过JSON动态路由发送UnsupportedBytesParameter参数。Bytes
Envelope Decision Table
信封字段决策表
| Goal | | | Notes |
|---|---|---|---|
| Simple read | | | |
| Conditional step after prior step | | | Conditions: |
| Single mutation | | | See EXAMPLES.md §Write |
| Upsert | | Multi-entry: load → | See EXAMPLES.md §Upsert |
| Per-row iteration over a param | | | |
| Warm a read | | normal body + header | Returns |
| 目标 | | | 说明 |
|---|---|---|---|
| 简单读取 | | | |
| 前置步骤后的条件执行 | | | 条件类型: |
| 单个突变操作 | | 包含突变步骤的 | 请参阅EXAMPLES.md §Write |
| 更新插入(Upsert) | | 多条目:加载 → | 请参阅EXAMPLES.md §Upsert |
| 遍历参数中的每一行 | | | |
| 预热读取请求 | | 标准请求体 + 请求头 | 成功时返回 |
AST Quick-Map
AST快速参考
Step categories and their JSON form (one-liners). Full signatures in .
REFERENCE.mdSources (start a traversal):
- /
{"N": {"Ids": [1,2]}}/{"N": {"Var": "x"}}— nodes by id / variable / parameter{"N": {"Param": "ids"}} - — nodes matching a source-safe predicate
{"NWhere": <SourcePredicate>} - /
{"E": {...}}— edges{"EWhere": <SourcePredicate>} {"VectorSearchNodes": {"label":"...","property":"...","query_vector":{...},"k":{...},"tenant_value":{...}}}- — BM25 on nodes
{"TextSearchNodes": {...}} - ,
{"VectorSearchEdges": {...}}{"TextSearchEdges": {...}}
Traversal (navigate):
- /
{"Out": "LABEL"}— also{"Out": null},In,Both,OutE,InE(same shape)BothE - /
"OutN"/"InN"— unit variants, from an edge stream back to a node"OtherN"
Filters:
- — property equals
{"Has": ["prop", {"String": "v"}]} - ,
{"HasLabel": "User"}{"HasKey": "email"} - — full predicate
{"Where": <Predicate>} - — unit variant
"Dedup" - ,
{"Within": "var"}— set ops against a stored variable{"Without": "var"} - ,
{"EdgeHas": ["weight", {"Value": {"I64": 1}}]}{"EdgeHasLabel": "KNOWS"}
Limits:
- ,
{"Limit": 10},{"Skip": 5}— literal{"Range": [0, 25]} - ,
{"LimitBy": {"Param": "n"}},{"SkipBy": ...}— runtime{"RangeBy": [<StreamBound>, <StreamBound>]}
Variables:
- /
{"As": "x"}— name the current stream{"Store": "x"} - — replace stream with a stored var
{"Select": "x"} - — inject var into stream (source or mid-traversal)
{"Inject": "x"}
Ordering:
- — single property
{"OrderBy": ["created_at", "Desc"]} {"OrderByMultiple": [["priority", "Desc"], ["name", "Asc"]]}
Aggregation:
- ,
{"Group": "status"}{"GroupCount": "status"} - — functions:
{"AggregateBy": ["Sum", "price"]},Count,Sum,Min,MaxMean
Branching (each branch is a = ):
SubTraversal{"steps": [...]}{"Union": [{"steps":[...]}, {"steps":[...]}]}{"Choose": {"condition": <Predicate>, "then_traversal": {"steps":[...]}, "else_traversal": null}}{"Coalesce": [{"steps":[...]}, ...]}{"Optional": {"steps":[...]}}
Repeat:
{"Repeat": {"traversal": {"steps":[{"Out":null}]}, "times": 3, "until": null, "emit": "After", "emit_predicate": null, "max_depth": 100}}- is one of
emit,"None","Before","After""All"
Projections (terminal):
{"Values": ["name", "email"]}- or
{"ValueMap": ["$id", "name"]}for all{"ValueMap": null} - — no
{"Project": [{"source":"name","alias":"name"}, {"alias":"age_plus_one","expr":{"Add":[{"Property":"age"},{"Constant":{"I64":1}}]}}]}/{"Property":...}wrapper (untagged){"Expr":...} - — unit variant
"EdgeProperties"
Terminals (scalar result):
- ,
"Count","Exists","Id""Label"
Mutations (write-only):
{"AddN": {"label": "User", "properties": [["name", {"Value": {"String": "Alice"}}]]}}{"AddE": {"label": "FOLLOWS", "to": {"Ids":[42]}, "properties": []}}- ,
{"SetProperty": ["name", {"Value": {"String": "Bob"}}]}{"RemoveProperty": "temp"} - — delete current nodes & their edges
"Drop" - ,
{"DropEdge": {"Ids": [42]}},{"DropEdgeLabeled": {"to": {...}, "label": "X"}}{"DropEdgeById": {"Ids": [7]}}
Indexes (write-only):
- ,
{"CreateIndex": {"spec": <IndexSpec>, "if_not_exists": true}}{"DropIndex": {"spec": <IndexSpec>}} - Legacy vector/text convenience steps: ,
{"CreateVectorIndexNodes": {...}},CreateVectorIndexEdges,CreateTextIndexNodesCreateTextIndexEdges
Reserved (currently no-ops — safe to include but have no effect): , , , , , , , .
"Fold""Unfold""Path""SimplePath"{"WithSack": <PropertyValue>}{"SackSet": "prop"}{"SackAdd": "prop"}"SackGet"步骤分类及其JSON格式(单行示例)。完整签名请参阅。
REFERENCE.md数据源(启动遍历):
- /
{"N": {"Ids": [1,2]}}/{"N": {"Var": "x"}}— 通过ID/变量/参数指定节点{"N": {"Param": "ids"}} - — 匹配源安全谓词的节点
{"NWhere": <SourcePredicate>} - /
{"E": {...}}— 边{"EWhere": <SourcePredicate>} {"VectorSearchNodes": {"label":"...","property":"...","query_vector":{...},"k":{...},"tenant_value":{...}}}- — 节点的BM25文本搜索
{"TextSearchNodes": {...}} - ,
{"VectorSearchEdges": {...}}{"TextSearchEdges": {...}}
遍历(导航):
- /
{"Out": "LABEL"}— 同样适用于{"Out": null}、In、Both、OutE、InE(结构相同)BothE - /
"OutN"/"InN"— 单元变体,从边流返回至节点"OtherN"
过滤器:
- — 属性等于指定值
{"Has": ["prop", {"String": "v"}]} - ,
{"HasLabel": "User"}{"HasKey": "email"} - — 完整谓词过滤
{"Where": <Predicate>} - — 单元变体,去重
"Dedup" - ,
{"Within": "var"}— 与存储变量的集合操作{"Without": "var"} - ,
{"EdgeHas": ["weight", {"Value": {"I64": 1}}]}{"EdgeHasLabel": "KNOWS"}
限制:
- ,
{"Limit": 10},{"Skip": 5}— 字面量{"Range": [0, 25]} - ,
{"LimitBy": {"Param": "n"}},{"SkipBy": ...}— 运行时参数{"RangeBy": [<StreamBound>, <StreamBound>]}
变量:
- /
{"As": "x"}— 为当前流命名{"Store": "x"} - — 用存储变量替换当前流
{"Select": "x"} - — 将变量注入流中(数据源或遍历中途)
{"Inject": "x"}
排序:
- — 单属性排序
{"OrderBy": ["created_at", "Desc"]} - — 多属性排序
{"OrderByMultiple": [["priority", "Desc"], ["name", "Asc"]]}
聚合:
- ,
{"Group": "status"}{"GroupCount": "status"} - — 聚合函数:
{"AggregateBy": ["Sum", "price"]}、Count、Sum、Min、MaxMean
分支(每个分支是 = ):
SubTraversal{"steps": [...]}{"Union": [{"steps":[...]}, {"steps":[...]}]}{"Choose": {"condition": <Predicate>, "then_traversal": {"steps":[...]}, "else_traversal": null}}{"Coalesce": [{"steps":[...]}, ...]}{"Optional": {"steps":[...]}}
重复遍历:
{"Repeat": {"traversal": {"steps":[{"Out":null}]}, "times": 3, "until": null, "emit": "After", "emit_predicate": null, "max_depth": 100}}- 可选值为
emit,"None","Before","After""All"
投影(终端操作):
{"Values": ["name", "email"]}- 或
{"ValueMap": ["$id", "name"]}(返回所有属性){"ValueMap": null} - — 请勿添加
{"Project": [{"source":"name","alias":"name"}, {"alias":"age_plus_one","expr":{"Add":[{"Property":"age"},{"Constant":{"I64":1}}]}}]}/{"Property":...}包裹(无标签枚举){"Expr":...} - — 单元变体,返回边属性
"EdgeProperties"
终端操作(标量结果):
- ,
"Count","Exists","Id""Label"
突变操作(仅写入):
{"AddN": {"label": "User", "properties": [["name", {"Value": {"String": "Alice"}}]]}}{"AddE": {"label": "FOLLOWS", "to": {"Ids":[42]}, "properties": []}}- ,
{"SetProperty": ["name", {"Value": {"String": "Bob"}}]}{"RemoveProperty": "temp"} - — 删除当前节点及其关联边
"Drop" - ,
{"DropEdge": {"Ids": [42]}},{"DropEdgeLabeled": {"to": {...}, "label": "X"}}{"DropEdgeById": {"Ids": [7]}}
索引操作(仅写入):
- ,
{"CreateIndex": {"spec": <IndexSpec>, "if_not_exists": true}}{"DropIndex": {"spec": <IndexSpec>}} - 遗留的向量/文本便捷步骤:,
{"CreateVectorIndexNodes": {...}},CreateVectorIndexEdges,CreateTextIndexNodesCreateTextIndexEdges
保留操作(当前无实际作用——可安全添加但无效果):, , , , , , , 。
"Fold""Unfold""Path""SimplePath"{"WithSack": <PropertyValue>}{"SackSet": "prop"}{"SackAdd": "prop"}"SackGet"Virtual Fields
虚拟字段
Available in projections, , and predicates without being declared in your schema:
value_mapHas- — node or edge id
$id - — node or edge label
$label - — on vector / text search hits; order is ascending (smaller = closer)
$distance - ,
$from— on edge streams (including$to) and edge vector/text hitsedge_properties
Distance lifecycle: is present on the direct hit stream produced by / / / . It is lost once traversal steps off the hit stream (, , , , , ). Project the distance before navigating if you need to keep it.
$distanceVectorSearchNodesVectorSearchEdgesTextSearchNodesTextSearchEdgesOutInBothOutNInNOtherN在投影、和谓词中可用,无需在Schema中声明:
value_mapHas- — 节点或边的ID
$id - — 节点或边的标签
$label - — 向量/文本搜索结果中的距离值;按升序排列(值越小越接近)
$distance - ,
$from— 边流(包括$to)和边向量/文本搜索结果中可用edge_properties
距离生命周期:存在于///生成的直接结果流中。一旦执行遍历步骤离开结果流(、、、、、),该字段会丢失。如需保留,请在导航前投影距离值。
$distanceVectorSearchNodesVectorSearchEdgesTextSearchNodesTextSearchEdgesOutInBothOutNInNOtherNParameter Typing Rules
参数类型规则
Use when Helix must coerce JSON into a specific parameter type. Every type string is a .
parameter_typesQueryParamType当Helix需要将JSON强制转换为特定参数类型时,使用。所有类型字符串均为。
parameter_typesQueryParamTypeType string encoding
类型字符串编码
Unit scalars serialize as bare strings:
text
"Bool" | "I64" | "F64" | "F32" | "String" | "DateTime" | "Bytes" | "Value" | "Object"Arrayjson
{"Array": "String"} // array of strings
{"Array": {"Array": "F64"}} // array of arrays of F64
{"Array": "Object"} // array of objectsRequired any time the value needs a non-default interpretation: , typed scalar coercion, or arrays whose element shape the runtime must know.
DateTime单元标量序列化为纯字符串:
text
"Bool" | "I64" | "F64" | "F32" | "String" | "DateTime" | "Bytes" | "Value" | "Object"Arrayjson
{"Array": "String"} // 字符串数组
{"Array": {"Array": "F64"}} // F64二维数组
{"Array": "Object"} // 对象数组当值需要非默认解释时必须使用:、标量类型强制转换,或运行时需知晓元素结构的数组。
DateTimeDateTime
DateTime示例
json
{
"parameters": {"created_after": "2026-04-05T10:00:00Z"},
"parameter_types": {"created_after": "DateTime"}
}Accepted value forms: RFC3339 string, epoch-millis integer. No implicit coercion — a plain string parameter without the type declaration is just a string.
json
{
"parameters": {"created_after": "2026-04-05T10:00:00Z"},
"parameter_types": {"created_after": "DateTime"}
}接受的值格式:RFC3339字符串、时间戳毫秒整数。无隐式类型转换——未声明类型的纯字符串参数仅会被视为普通字符串。
Typed array example
类型化数组示例
json
{
"parameters": {"statuses": ["active", "pending"]},
"parameter_types": {"statuses": {"Array": "String"}}
}json
{
"parameters": {"statuses": ["active", "pending"]},
"parameter_types": {"statuses": {"Array": "String"}}
}Vector array example
向量数组示例
json
{
"parameters": {"query_vector": [0.12, 0.44, 0.91]},
"parameter_types": {"query_vector": {"Array": "F64"}}
}json
{
"parameters": {"query_vector": [0.12, 0.44, 0.91]},
"parameter_types": {"query_vector": {"Array": "F64"}}
}Unsupported Bytes
不支持的Bytes类型
Do not send parameters through the JSON dynamic route. The builder raises and the gateway cannot round-trip the shape.
BytesUnsupportedBytesParameter请勿通过JSON动态路由发送参数。构建器会抛出错误,且网关无法处理该类型的往返序列化。
BytesUnsupportedBytesParameterRead Versus Write Rules
读取与写入规则
- — no mutation / index step may appear anywhere in the AST.
request_type: "read" - — allowed to mix read steps and mutation / index steps in the same batch.
request_type: "write"
Dynamic requests do not support a request type. That's only for the stored-route / MCP tool surface.
"mcp"If the inline AST contains a write step, the request must also be marked — the gateway uses to pick the transaction kind.
"write"request_type- — AST中不得包含任何突变/索引步骤。
request_type: "read" - — 允许在同一批处理中混合读取步骤与突变/索引步骤。
request_type: "write"
动态请求不支持请求类型,该类型仅适用于存储式路由/MCP工具。
"mcp"如果内联AST包含写入步骤,请求必须同时标记为——网关通过选择事务类型。
"write"request_typeQuery Warming
查询预热
Dynamic query warming uses the same request body plus the header:
text
X-Helix-Warm: trueRules:
- only supported for reads
- rejected for writes
- successful warm requests return
204 No Content
动态查询预热使用相同的请求体,添加以下请求头:
text
X-Helix-Warm: true规则:
- 仅支持读取请求
- 写入请求会被拒绝
- 成功的预热请求返回
204 No Content
Practical Workflow
实用工作流
- Prefer a stored route if the query is stable and production-facing.
- If using the dynamic route, locate or generate the exact inline AST first — either serialize from a Rust
queryor copy from a test fixture.DynamicQueryRequest::read(...).to_json_string() - Add only for the names the AST expects.
parameters - Add for
parameter_types, typed arrays, and any other parameters needing schema-aware coercion.DateTime - Validate that the body contains one inline route object, not a full query bundle.
- If warming, ensure the request is read-only and add .
X-Helix-Warm: true
- 如果查询稳定且面向生产环境,优先选择存储式路由。
- 如果使用动态路由,先定位或生成准确的内联AST——可通过Rust代码
query序列化,或从测试 fixture 中复制。DynamicQueryRequest::read(...).to_json_string() - 仅添加AST所需名称的。
parameters - 为、类型化数组及其他需要基于Schema类型转换的参数添加
DateTime。parameter_types - 验证请求体包含单个内联路由对象,而非完整的查询包。
- 如果需要预热,确保请求为只读并添加请求头。
X-Helix-Warm: true
Anti-Patterns
反模式
Do not:
- send the full file under
queries.json— send a single route (thequery/ReadBatchinline)WriteBatch - use as the dynamic request type
"mcp" - capitalize /
"Read"in"Write"— the enum is lowercaserequest_type - rely on implicit parsing without
DateTimeparameter_types - send parameters
Bytes - invent inline AST variant names such as when the parser expects
N.Id,N.Ids, orN.Var. The parser rejects withN.Param. Same foot-gun forunknown variant 'Id', expected one of 'Ids', 'Var', 'Param'(single vs array),Hasordering (alwaysOrderBy, not[prop, Order]), and{prop: Order}entries (noProject/{"Property": ...}wrapper — the enum is untagged).{"Expr": ...} - hand-wave typed array encoding if you have not verified it locally — copy from or a recorded request
tests/register_metadata_tests.rs - wrap entries with a variant tag —
ProjectionisProjection#[serde(untagged)] - wrap top-level parameter values with variant tags — is untagged (bare JSON)
DynamicQueryValue - default to dynamic queries for stable production traffic
请勿:
- 将完整的文件放在
queries.json字段下——应发送单个路由(内联的query/ReadBatch)WriteBatch - 使用作为动态请求类型
"mcp" - 在中大写
request_type/"Read"——枚举为小写"Write" - 依赖无的隐式
parameter_types解析DateTime - 发送参数
Bytes - 自行发明内联AST变体名称,例如解析器期望、
N.Ids或N.Var时使用N.Param。解析器会返回错误N.Id。类似的错误场景包括unknown variant 'Id', expected one of 'Ids', 'Var', 'Param'(单个值 vs 数组)、Has排序格式(必须为OrderBy,而非[prop, Order])、{prop: Order}条目(无Project/{"Property": ...}包裹——枚举为无标签)。{"Expr": ...} - 在未本地验证的情况下随意编写类型化数组编码——请从或已记录的请求中复制
tests/register_metadata_tests.rs - 为条目添加变体标签——
Projection是Projection#[serde(untagged)] - 为顶层参数值添加变体标签——是无标签的(纯JSON)
DynamicQueryValue - 默认使用动态查询处理稳定的生产流量
Validation Checklist
验证检查清单
Before finishing:
- target endpoint is
POST /v1/query - is
request_typeor"read"(lowercase)"write" - is a single inline route object (a
queryorReadBatch), not a bundleWriteBatch - entries are
queries[*]or{"Query": {...}}, each{"ForEach": {...}}hasQuery,name,stepscondition - unit-variant steps are encoded as bare strings (,
"Count","Dedup","Exists","Id","Label","OutN","InN","OtherN","EdgeProperties")"Drop" - tuple-variant steps with 2+ fields use arrays ()
{"Has": ["name", {"String": "v"}]} - struct-variant steps use objects ()
{"VectorSearchNodes": {"label": ...}} - entries have no variant wrapper (untagged enum)
Project - inner AST values use tagged (
PropertyValue); top-level{"I64": 1}values are bare JSON (parameters)1 - covers every parameter that needs typed coercion (
parameter_types, typed arrays)DateTime - parameters are RFC3339 strings or epoch-millis integers and declared in
DateTimeparameter_types - no parameters
Bytes - warming is only applied to reads
- if the AST contains any mutation or index step, is
request_type"write"
完成前请检查:
- 目标端点为
POST /v1/query - 为
request_type或"read"(小写)"write" - 是单个内联路由对象(
query或ReadBatch),而非查询包WriteBatch - 条目为
queries[*]或{"Query": {...}},每个{"ForEach": {...}}包含Query、name、stepscondition - 单元变体步骤编码为纯字符串(,
"Count","Dedup","Exists","Id","Label","OutN","InN","OtherN","EdgeProperties")"Drop" - 带2个及以上字段的元组变体步骤使用数组()
{"Has": ["name", {"String": "v"}]} - 结构体变体步骤使用对象()
{"VectorSearchNodes": {"label": ...}} - 条目无变体包裹(无标签枚举)
Project - AST内部值使用带标签的(
PropertyValue);顶层{"I64": 1}值为纯JSON(parameters)1 - 包含所有需要类型强制转换的参数(
parameter_types、类型化数组)DateTime - 参数为RFC3339字符串或时间戳毫秒整数且已在
DateTime中声明parameter_types - 无参数
Bytes - 仅对读取请求应用预热
- 如果AST包含任何突变或索引步骤,为
request_type"write"
Source References
源码参考
Authoritative source files (for when the reference answer is ambiguous):
- —
src/lib.rs:2506-2962enum (every variant)Step - —
src/lib.rs:1548-1596;Predicate—src/lib.rs:1603-1626SourcePredicate - —
src/lib.rs:1352-1384Expr - —
src/lib.rs:972-1002;PropertyValue—src/lib.rs:1197-1202PropertyInput - —
src/lib.rs:1232-1339/NodeRefEdgeRef - —
src/lib.rs:1888-1965/PropertyProjection/ExprProjection(untagged)Projection - —
src/lib.rs:2250-2323;RepeatConfig—src/lib.rs:1984-1993EmitBehavior - —
src/lib.rs:2327-2398IndexSpec - —
src/lib.rs:4041-4078,BatchCondition,BatchEntryNamedQuery - —
src/lib.rs:4089-4270/ReadBatch/WriteBatch(untagged)BatchQuery - —
src/lib.rs:4346-4452(lowercase),DynamicQueryRequestType(untagged),DynamicQueryValueDynamicQueryRequest - —
src/query_generator.rs:9-31QueryParamType - — ground-truth serialized examples
tests/register_metadata_tests.rs:182-186, 243-245, 274-275
权威源码文件(当参考文档存在歧义时使用):
- —
src/lib.rs:2506-2962枚举(所有变体)Step - —
src/lib.rs:1548-1596;Predicate—src/lib.rs:1603-1626SourcePredicate - —
src/lib.rs:1352-1384Expr - —
src/lib.rs:972-1002;PropertyValue—src/lib.rs:1197-1202PropertyInput - —
src/lib.rs:1232-1339/NodeRefEdgeRef - —
src/lib.rs:1888-1965/PropertyProjection/ExprProjection(无标签)Projection - —
src/lib.rs:2250-2323;RepeatConfig—src/lib.rs:1984-1993EmitBehavior - —
src/lib.rs:2327-2398IndexSpec - —
src/lib.rs:4041-4078,BatchCondition,BatchEntryNamedQuery - —
src/lib.rs:4089-4270/ReadBatch/WriteBatch(无标签)BatchQuery - —
src/lib.rs:4346-4452(小写),DynamicQueryRequestType(无标签),DynamicQueryValueDynamicQueryRequest - —
src/query_generator.rs:9-31QueryParamType - — 经过验证的序列化示例
tests/register_metadata_tests.rs:182-186, 243-245, 274-275