helix-query-json-dynamic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Helix Dynamic Query JSON

Helix 动态查询 JSON

Use this skill for inline dynamic query requests sent directly to
POST /v1/query
.
The inline
query
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
REFERENCE.md
first
— do not guess variant names or field shapes.
本技能适用于直接发送至
POST /v1/query
的内联动态查询请求。
内联
query
请求体是Rust DSL AST的JSON序列化形式。Agent可发送的所有变体均记录在配套文件中。如果您要编写的查询超出简单读取范畴,请先打开
REFERENCE.md
——请勿猜测变体名称或字段结构。

Reference Files

参考文件

  • REFERENCE.md
    — complete AST variant catalog (every
    Step
    ,
    Predicate
    ,
    Expr
    ,
    PropertyValue
    ,
    IndexSpec
    ,
    RepeatConfig
    ,
    BatchCondition
    , envelope field). Use when writing a non-trivial request.
  • EXAMPLES.md
    — working end-to-end JSON bodies: reads, writes, vector/text search,
    Repeat
    ,
    Choose
    ,
    Coalesce
    ,
    Union
    , aggregations, upserts,
    ForEach
    , index management, warming. Copy the closest scenario as a starting point.
  • REFERENCE.md
    — 完整的AST变体目录(包含所有
    Step
    Predicate
    Expr
    PropertyValue
    IndexSpec
    RepeatConfig
    BatchCondition
    及信封字段)。编写非简单请求时使用。
  • EXAMPLES.md
    — 可直接运行的端到端JSON请求体:读取、写入、向量/文本搜索、
    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
    POST /v1/query
    call
  • add
    parameter_types
    to a dynamic request
  • send
    DateTime
    or typed-array parameters correctly
  • 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
helix-query-authoring
for that.
当您需要完成以下任务时,可使用本技能:
  • 构建Helix动态请求体
  • 调试失败的
    POST /v1/query
    调用
  • 为动态请求添加
    parameter_types
  • 正确发送
    DateTime
    或类型化数组参数
  • 理解动态路由的读取与写入行为差异
  • 为动态读取请求启用查询预热
  • 将已有的Rust DSL查询转换为JSON形式
请勿将本技能作为编写存储式Rust DSL查询函数的主要指南,此类场景请使用
helix-query-authoring

First Steps

前期步骤

Before writing the payload:
  1. 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.
  2. Confirm whether the request is a read or a write. A query that contains any mutation step (
    AddN
    ,
    AddE
    ,
    SetProperty
    ,
    RemoveProperty
    ,
    Drop
    ,
    DropEdge
    ,
    DropEdgeLabeled
    ,
    DropEdgeById
    , or any
    Create*Index
    /
    DropIndex
    ) must use
    request_type: "write"
    .
  3. Confirm whether the inline
    query
    object already exists in code, a test, or a serialized payload — prefer copying a known-good shape.
  4. Identify any parameters that need explicit typing, especially
    DateTime
    and typed arrays.
编写请求负载前,请完成以下操作:
  1. 判断该请求是否更适合存储式路由而非动态路由。如果请求属于稳态应用流量,优先选择存储式路由。
  2. 确认请求类型为读取或写入。包含任何突变步骤(
    AddN
    AddE
    SetProperty
    RemoveProperty
    Drop
    DropEdge
    DropEdgeLabeled
    DropEdgeById
    ,或任何
    Create*Index
    /
    DropIndex
    )的查询必须设置
    request_type: "write"
  3. 确认内联
    query
    对象是否已存在于代码、测试用例或序列化负载中——优先复制已知可用的结构。
  4. 识别需要显式类型声明的参数,尤其是
    DateTime
    和类型化数组。

Required Envelope Rules

信封字段规则

  • send requests to
    POST /v1/query
  • request_type
    must be
    "read"
    or
    "write"
    (lowercase — the enum uses
    #[serde(rename_all = "lowercase")]
    )
  • query
    must be a single inline route object (a
    ReadBatch
    or
    WriteBatch
    ), not the full
    queries.json
    bundle
  • parameters
    is optional
  • parameter_types
    is optional until you need schema-aware coercion (see Parameter Typing)
  • X-Helix-Warm: true
    is an optional request header, valid only for reads
  • 请求发送至
    POST /v1/query
  • request_type
    必须为
    "read"
    "write"
    小写——枚举使用
    #[serde(rename_all = "lowercase")]
  • query
    必须是单个内联路由对象(
    ReadBatch
    WriteBatch
    ),不能是完整的
    queries.json
  • parameters
    为可选字段
  • parameter_types
    为可选字段,仅当需要基于Schema的类型转换时使用(请参阅参数类型部分)
  • 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:
  • query
    contains a
    ReadBatch
    (or
    WriteBatch
    ); both have
    { "queries": [...], "returns": [...] }
    .
  • Each element of
    queries
    is a
    BatchEntry
    — either
    {"Query": {...}}
    or
    {"ForEach": {...}}
    .
  • "steps": ["Count"]
    is a valid step list:
    Count
    is a unit variant so it serializes as a bare string. Data-carrying variants are wrapped:
    {"Limit": 10}
    ,
    {"Has": ["name", {"String": "Alice"}]}
    , etc.
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
REFERENCE.md
follows these rules. Internalize them or the request will fail with
unknown variant
/
invalid type
errors.
  1. Default encoding is externally tagged. Given a Rust enum
    E::Var(..)
    without a
    #[serde(...)]
    attribute:
    • Unit variant (no data): bare string.
      Step::Count
      "Count"
      .
      Predicate::HasKey
      is a tuple-with-data variant, not unit — see rule 2.
    • 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": "...", ...}}
      .
  2. Three enums are
    #[serde(untagged)]
    — no variant wrapper:
    • BatchQuery
      (the value of the envelope's
      query
      field): write the
      ReadBatch
      /
      WriteBatch
      object inline. There is no
      {"Read": ...}
      wrapper.
    • Projection
      (element of a
      Project
      step's list): write the inner struct directly.
      PropertyProjection
      {"source": "name", "alias": "name"}
      .
      ExprProjection
      {"alias": "age_plus_one", "expr": {...}}
      . Do not write
      {"Property": {...}}
      or
      {"Expr": {...}}
      wrappers.
    • DynamicQueryValue
      (values inside the top-level
      parameters
      map): bare JSON.
      "limit": 25
      ,
      "tags": ["a","b"]
      ,
      "user": {"name": "Alice"}
      . No
      {"I64": 25}
      wrapping here — that form is
      PropertyValue
      , which is inside the AST, not at parameter-value position.
  3. DynamicQueryRequestType
    is
    rename_all = "lowercase"
    : use
    "read"
    /
    "write"
    , never
    "Read"
    /
    "Write"
    .
  4. Optional fields may be omitted or set to
    null
    .
    tenant_value
    ,
    condition
    ,
    else_traversal
    ,
    emit_predicate
    , and similar all serialize via
    skip_serializing_if = "Option::is_none"
    when unset, but the server accepts explicit
    null
    .
  5. PropertyValue
    is distinct from
    DynamicQueryValue
    .
    Inside the AST (literals in
    Has
    ,
    Eq
    ,
    AddN
    properties wrapped in
    PropertyInput::Value
    , etc.) values are tagged:
    {"String": "..."}
    ,
    {"I64": 42}
    ,
    {"Bool": true}
    ,
    {"F64": 3.14}
    ,
    {"F64Array": [0.1, 0.2]}
    ,
    {"Null": null}
    is wrong — use the bare string
    "Null"
    for the unit variant. At parameter-value position (top-level
    parameters
    map) values are untagged bare JSON.
  6. DateTime
    over JSON:
    supply an RFC3339 string or epoch-millis integer as the parameter value, and declare
    parameter_types: {"p": "DateTime"}
    . No implicit coercion — a plain string parameter without the type declaration is just a string.
  7. Bytes
    is not round-trippable.
    The builder raises
    UnsupportedBytesParameter
    . Do not send
    Bytes
    parameters through the JSON dynamic route.
REFERENCE.md
中的所有编码均遵循以下规则。请牢记这些规则,否则请求会因
unknown variant
/
invalid type
错误失败。
  1. 默认编码为外部标签式。对于未添加
    #[serde(...)]
    属性的Rust枚举
    E::Var(..)
    • 单元变体(无数据):纯字符串。
      Step::Count
      "Count"
      Predicate::HasKey
      是带数据的元组变体,不属于单元变体——请参阅规则2。
    • 带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": "...", ...}}
  2. 三个枚举采用
    #[serde(untagged)]
    ——无变体包裹
    • BatchQuery
      (信封
      query
      字段的值):直接内联写入
      ReadBatch
      /
      WriteBatch
      对象。不需要
      {"Read": ...}
      包裹。
    • Projection
      Project
      步骤列表中的元素):直接写入内部结构体。
      PropertyProjection
      {"source": "name", "alias": "name"}
      ExprProjection
      {"alias": "age_plus_one", "expr": {...}}
      请勿写入
      {"Property": {...}}
      {"Expr": {...}}
      包裹。
    • DynamicQueryValue
      (顶层
      parameters
      映射中的值):纯JSON。
      "limit": 25
      "tags": ["a","b"]
      "user": {"name": "Alice"}
      。此处不需要
      {"I64": 25}
      包裹——该格式是
      PropertyValue
      ,用于AST内部,而非参数值位置。
  3. DynamicQueryRequestType
    采用
    rename_all = "lowercase"
    :使用
    "read"
    /
    "write"
    ,切勿使用
    "Read"
    /
    "Write"
  4. 可选字段可省略或设为
    null
    tenant_value
    condition
    else_traversal
    emit_predicate
    及类似字段在未设置时通过
    skip_serializing_if = "Option::is_none"
    序列化,但服务器也接受显式的
    null
  5. PropertyValue
    DynamicQueryValue
    不同
    。AST内部(
    Has
    Eq
    中的字面量,
    AddN
    属性中包裹在
    PropertyInput::Value
    中的值等)的值是带标签的
    {"String": "..."}
    {"I64": 42}
    {"Bool": true}
    {"F64": 3.14}
    {"F64Array": [0.1, 0.2]}
    ;单元变体
    Null
    需使用纯字符串
    "Null"
    ,而非
    {"Null": null}
    。在参数值位置(顶层
    parameters
    映射)的值是无标签的纯JSON。
  6. JSON中的
    DateTime
    :参数值可提供RFC3339字符串或时间戳毫秒整数,并声明
    parameter_types: {"p": "DateTime"}
    。无隐式类型转换——未声明类型的纯字符串参数仅会被视为普通字符串。
  7. Bytes
    类型不支持往返序列化
    。构建器会抛出
    UnsupportedBytesParameter
    错误。请勿通过JSON动态路由发送
    Bytes
    参数。

Envelope Decision Table

信封字段决策表

Goal
request_type
query.queries[*]
shape
Notes
Simple read
"read"
{"Query": {"name": "...", "steps": [...], "condition": null}}
Conditional step after prior step
"read"
or
"write"
{"Query": {..., "condition": {"VarNotEmpty": "prev"}}}
Conditions:
VarNotEmpty
,
VarEmpty
,
VarMinSize
,
PrevNotEmpty
Single mutation
"write"
{"Query": {...}}
with a mutation step
See EXAMPLES.md §Write
Upsert
"write"
Multi-entry: load →
VarNotEmpty
update →
VarEmpty
create
See EXAMPLES.md §Upsert
Per-row iteration over a param
"read"
or
"write"
{"ForEach": {"param": "items", "body": [...]}}
param
must be typed
["Array", "Object"]
Warm a read
"read"
normal body + header
X-Helix-Warm: true
Returns
204 No Content
on success
目标
request_type
query.queries[*]
结构
说明
简单读取
"read"
{"Query": {"name": "...", "steps": [...], "condition": null}}
前置步骤后的条件执行
"read"
"write"
{"Query": {..., "condition": {"VarNotEmpty": "prev"}}}
条件类型:
VarNotEmpty
VarEmpty
VarMinSize
PrevNotEmpty
单个突变操作
"write"
包含突变步骤的
{"Query": {...}}
请参阅EXAMPLES.md §Write
更新插入(Upsert)
"write"
多条目:加载 →
VarNotEmpty
更新 →
VarEmpty
创建
请参阅EXAMPLES.md §Upsert
遍历参数中的每一行
"read"
"write"
{"ForEach": {"param": "items", "body": [...]}}
param
必须声明类型为
["Array", "Object"]
预热读取请求
"read"
标准请求体 + 请求头
X-Helix-Warm: true
成功时返回
204 No Content

AST Quick-Map

AST快速参考

Step categories and their JSON form (one-liners). Full signatures in
REFERENCE.md
.
Sources (start a traversal):
  • {"N": {"Ids": [1,2]}}
    /
    {"N": {"Var": "x"}}
    /
    {"N": {"Param": "ids"}}
    — nodes by id / variable / parameter
  • {"NWhere": <SourcePredicate>}
    — nodes matching a source-safe predicate
  • {"E": {...}}
    /
    {"EWhere": <SourcePredicate>}
    — edges
  • {"VectorSearchNodes": {"label":"...","property":"...","query_vector":{...},"k":{...},"tenant_value":{...}}}
  • {"TextSearchNodes": {...}}
    — BM25 on nodes
  • {"VectorSearchEdges": {...}}
    ,
    {"TextSearchEdges": {...}}
Traversal (navigate):
  • {"Out": "LABEL"}
    /
    {"Out": null}
    — also
    In
    ,
    Both
    ,
    OutE
    ,
    InE
    ,
    BothE
    (same shape)
  • "OutN"
    /
    "InN"
    /
    "OtherN"
    — unit variants, from an edge stream back to a node
Filters:
  • {"Has": ["prop", {"String": "v"}]}
    — property equals
  • {"HasLabel": "User"}
    ,
    {"HasKey": "email"}
  • {"Where": <Predicate>}
    — full predicate
  • "Dedup"
    — unit variant
  • {"Within": "var"}
    ,
    {"Without": "var"}
    — set ops against a stored variable
  • {"EdgeHas": ["weight", {"Value": {"I64": 1}}]}
    ,
    {"EdgeHasLabel": "KNOWS"}
Limits:
  • {"Limit": 10}
    ,
    {"Skip": 5}
    ,
    {"Range": [0, 25]}
    — literal
  • {"LimitBy": {"Param": "n"}}
    ,
    {"SkipBy": ...}
    ,
    {"RangeBy": [<StreamBound>, <StreamBound>]}
    — runtime
Variables:
  • {"As": "x"}
    /
    {"Store": "x"}
    — name the current stream
  • {"Select": "x"}
    — replace stream with a stored var
  • {"Inject": "x"}
    — inject var into stream (source or mid-traversal)
Ordering:
  • {"OrderBy": ["created_at", "Desc"]}
    — single property
  • {"OrderByMultiple": [["priority", "Desc"], ["name", "Asc"]]}
Aggregation:
  • {"Group": "status"}
    ,
    {"GroupCount": "status"}
  • {"AggregateBy": ["Sum", "price"]}
    — functions:
    Count
    ,
    Sum
    ,
    Min
    ,
    Max
    ,
    Mean
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}}
  • emit
    is one of
    "None"
    ,
    "Before"
    ,
    "After"
    ,
    "All"
Projections (terminal):
  • {"Values": ["name", "email"]}
  • {"ValueMap": ["$id", "name"]}
    or
    {"ValueMap": null}
    for all
  • {"Project": [{"source":"name","alias":"name"}, {"alias":"age_plus_one","expr":{"Add":[{"Property":"age"},{"Constant":{"I64":1}}]}}]}
    no
    {"Property":...}
    /
    {"Expr":...}
    wrapper
    (untagged)
  • "EdgeProperties"
    — unit variant
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"}
  • "Drop"
    — delete current nodes & their edges
  • {"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
    ,
    CreateTextIndexNodes
    ,
    CreateTextIndexEdges
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"}}
    /
    {"N": {"Param": "ids"}}
    — 通过ID/变量/参数指定节点
  • {"NWhere": <SourcePredicate>}
    — 匹配源安全谓词的节点
  • {"E": {...}}
    /
    {"EWhere": <SourcePredicate>}
    — 边
  • {"VectorSearchNodes": {"label":"...","property":"...","query_vector":{...},"k":{...},"tenant_value":{...}}}
  • {"TextSearchNodes": {...}}
    — 节点的BM25文本搜索
  • {"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
    Max
    Mean
分支(每个分支是
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
    ,
    CreateTextIndexNodes
    ,
    CreateTextIndexEdges
保留操作(当前无实际作用——可安全添加但无效果)
"Fold"
,
"Unfold"
,
"Path"
,
"SimplePath"
,
{"WithSack": <PropertyValue>}
,
{"SackSet": "prop"}
,
{"SackAdd": "prop"}
,
"SackGet"

Virtual Fields

虚拟字段

Available in projections,
value_map
, and
Has
predicates without being declared in your schema:
  • $id
    — node or edge id
  • $label
    — node or edge label
  • $distance
    — on vector / text search hits; order is ascending (smaller = closer)
  • $from
    ,
    $to
    — on edge streams (including
    edge_properties
    ) and edge vector/text hits
Distance lifecycle:
$distance
is present on the direct hit stream produced by
VectorSearchNodes
/
VectorSearchEdges
/
TextSearchNodes
/
TextSearchEdges
. It is lost once traversal steps off the hit stream (
Out
,
In
,
Both
,
OutN
,
InN
,
OtherN
). Project the distance before navigating if you need to keep it.
在投影、
value_map
Has
谓词中可用,无需在Schema中声明:
  • $id
    — 节点或边的ID
  • $label
    — 节点或边的标签
  • $distance
    — 向量/文本搜索结果中的距离值;按升序排列(值越小越接近)
  • $from
    ,
    $to
    — 边流(包括
    edge_properties
    )和边向量/文本搜索结果中可用
距离生命周期
$distance
存在于
VectorSearchNodes
/
VectorSearchEdges
/
TextSearchNodes
/
TextSearchEdges
生成的直接结果流中。一旦执行遍历步骤离开结果流(
Out
In
Both
OutN
InN
OtherN
),该字段会丢失。如需保留,请在导航前投影距离值。

Parameter Typing Rules

参数类型规则

Use
parameter_types
when Helix must coerce JSON into a specific parameter type. Every type string is a
QueryParamType
.
当Helix需要将JSON强制转换为特定参数类型时,使用
parameter_types
。所有类型字符串均为
QueryParamType

Type string encoding

类型字符串编码

Unit scalars serialize as bare strings:
text
"Bool" | "I64" | "F64" | "F32" | "String" | "DateTime" | "Bytes" | "Value" | "Object"
Array
is a single-field tuple variant — it wraps its element type:
json
{"Array": "String"}                     // array of strings
{"Array": {"Array": "F64"}}             // array of arrays of F64
{"Array": "Object"}                     // array of objects
Required any time the value needs a non-default interpretation:
DateTime
, typed scalar coercion, or arrays whose element shape the runtime must know.
单元标量序列化为纯字符串:
text
"Bool" | "I64" | "F64" | "F32" | "String" | "DateTime" | "Bytes" | "Value" | "Object"
Array
是单字段元组变体——包裹其元素类型:
json
{"Array": "String"}                     // 字符串数组
{"Array": {"Array": "F64"}}             // F64二维数组
{"Array": "Object"}                     // 对象数组
当值需要非默认解释时必须使用:
DateTime
、标量类型强制转换,或运行时需知晓元素结构的数组。

DateTime

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
Bytes
parameters through the JSON dynamic route. The builder raises
UnsupportedBytesParameter
and the gateway cannot round-trip the shape.
请勿通过JSON动态路由发送
Bytes
参数。构建器会抛出
UnsupportedBytesParameter
错误,且网关无法处理该类型的往返序列化。

Read Versus Write Rules

读取与写入规则

  • request_type: "read"
    — no mutation / index step may appear anywhere in the AST.
  • request_type: "write"
    — allowed to mix read steps and mutation / index steps in the same batch.
Dynamic requests do not support a
"mcp"
request type. That's only for the stored-route / MCP tool surface.
If the inline AST contains a write step, the request must also be marked
"write"
— the gateway uses
request_type
to pick the transaction kind.
  • request_type: "read"
    — AST中不得包含任何突变/索引步骤。
  • request_type: "write"
    — 允许在同一批处理中混合读取步骤与突变/索引步骤。
动态请求不支持
"mcp"
请求类型,该类型仅适用于存储式路由/MCP工具。
如果内联AST包含写入步骤,请求必须同时标记为
"write"
——网关通过
request_type
选择事务类型。

Query Warming

查询预热

Dynamic query warming uses the same request body plus the header:
text
X-Helix-Warm: true
Rules:
  • only supported for reads
  • rejected for writes
  • successful warm requests return
    204 No Content
动态查询预热使用相同的请求体,添加以下请求头:
text
X-Helix-Warm: true
规则:
  • 仅支持读取请求
  • 写入请求会被拒绝
  • 成功的预热请求返回
    204 No Content

Practical Workflow

实用工作流

  1. Prefer a stored route if the query is stable and production-facing.
  2. If using the dynamic route, locate or generate the exact inline
    query
    AST first — either serialize from a Rust
    DynamicQueryRequest::read(...).to_json_string()
    or copy from a test fixture.
  3. Add
    parameters
    only for the names the AST expects.
  4. Add
    parameter_types
    for
    DateTime
    , typed arrays, and any other parameters needing schema-aware coercion.
  5. Validate that the body contains one inline route object, not a full query bundle.
  6. If warming, ensure the request is read-only and add
    X-Helix-Warm: true
    .
  1. 如果查询稳定且面向生产环境,优先选择存储式路由。
  2. 如果使用动态路由,先定位或生成准确的内联
    query
    AST——可通过Rust代码
    DynamicQueryRequest::read(...).to_json_string()
    序列化,或从测试 fixture 中复制。
  3. 仅添加AST所需名称的
    parameters
  4. DateTime
    、类型化数组及其他需要基于Schema类型转换的参数添加
    parameter_types
  5. 验证请求体包含单个内联路由对象,而非完整的查询包。
  6. 如果需要预热,确保请求为只读并添加
    X-Helix-Warm: true
    请求头。

Anti-Patterns

反模式

Do not:
  • send the full
    queries.json
    file under
    query
    — send a single route (the
    ReadBatch
    /
    WriteBatch
    inline)
  • use
    "mcp"
    as the dynamic request type
  • capitalize
    "Read"
    /
    "Write"
    in
    request_type
    — the enum is lowercase
  • rely on implicit
    DateTime
    parsing without
    parameter_types
  • send
    Bytes
    parameters
  • invent inline AST variant names such as
    N.Id
    when the parser expects
    N.Ids
    ,
    N.Var
    , or
    N.Param
    . The parser rejects with
    unknown variant 'Id', expected one of 'Ids', 'Var', 'Param'
    . Same foot-gun for
    Has
    (single vs array),
    OrderBy
    ordering (always
    [prop, Order]
    , not
    {prop: Order}
    ), and
    Project
    entries (no
    {"Property": ...}
    /
    {"Expr": ...}
    wrapper — the enum is untagged).
  • hand-wave typed array encoding if you have not verified it locally — copy from
    tests/register_metadata_tests.rs
    or a recorded request
  • wrap
    Projection
    entries with a variant tag —
    Projection
    is
    #[serde(untagged)]
  • wrap top-level parameter values with variant tags —
    DynamicQueryValue
    is untagged (bare JSON)
  • 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'
    。类似的错误场景包括
    Has
    (单个值 vs 数组)、
    OrderBy
    排序格式(必须为
    [prop, Order]
    ,而非
    {prop: Order}
    )、
    Project
    条目(无
    {"Property": ...}
    /
    {"Expr": ...}
    包裹——枚举为无标签)。
  • 在未本地验证的情况下随意编写类型化数组编码——请从
    tests/register_metadata_tests.rs
    或已记录的请求中复制
  • Projection
    条目添加变体标签——
    Projection
    #[serde(untagged)]
  • 为顶层参数值添加变体标签——
    DynamicQueryValue
    是无标签的(纯JSON)
  • 默认使用动态查询处理稳定的生产流量

Validation Checklist

验证检查清单

Before finishing:
  • target endpoint is
    POST /v1/query
  • request_type
    is
    "read"
    or
    "write"
    (lowercase)
  • query
    is a single inline route object (a
    ReadBatch
    or
    WriteBatch
    ), not a bundle
  • queries[*]
    entries are
    {"Query": {...}}
    or
    {"ForEach": {...}}
    , each
    Query
    has
    name
    ,
    steps
    ,
    condition
  • 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": ...}}
    )
  • Project
    entries have no variant wrapper (untagged enum)
  • inner AST values use tagged
    PropertyValue
    (
    {"I64": 1}
    ); top-level
    parameters
    values are bare JSON (
    1
    )
  • parameter_types
    covers every parameter that needs typed coercion (
    DateTime
    , typed arrays)
  • DateTime
    parameters are RFC3339 strings or epoch-millis integers and declared in
    parameter_types
  • no
    Bytes
    parameters
  • warming is only applied to reads
  • if the AST contains any mutation or index step,
    request_type
    is
    "write"
完成前请检查:
  • 目标端点为
    POST /v1/query
  • request_type
    "read"
    "write"
    (小写)
  • query
    是单个内联路由对象(
    ReadBatch
    WriteBatch
    ),而非查询包
  • queries[*]
    条目为
    {"Query": {...}}
    {"ForEach": {...}}
    ,每个
    Query
    包含
    name
    steps
    condition
  • 单元变体步骤编码为纯字符串(
    "Count"
    ,
    "Dedup"
    ,
    "Exists"
    ,
    "Id"
    ,
    "Label"
    ,
    "OutN"
    ,
    "InN"
    ,
    "OtherN"
    ,
    "EdgeProperties"
    ,
    "Drop"
  • 带2个及以上字段的元组变体步骤使用数组(
    {"Has": ["name", {"String": "v"}]}
  • 结构体变体步骤使用对象(
    {"VectorSearchNodes": {"label": ...}}
  • Project
    条目无变体包裹(无标签枚举)
  • AST内部值使用带标签的
    PropertyValue
    {"I64": 1}
    );顶层
    parameters
    值为纯JSON(
    1
  • parameter_types
    包含所有需要类型强制转换的参数(
    DateTime
    、类型化数组)
  • DateTime
    参数为RFC3339字符串或时间戳毫秒整数已在
    parameter_types
    中声明
  • Bytes
    参数
  • 仅对读取请求应用预热
  • 如果AST包含任何突变或索引步骤,
    request_type
    "write"

Source References

源码参考

Authoritative source files (for when the reference answer is ambiguous):
  • src/lib.rs:2506-2962
    Step
    enum (every variant)
  • src/lib.rs:1548-1596
    Predicate
    ;
    src/lib.rs:1603-1626
    SourcePredicate
  • src/lib.rs:1352-1384
    Expr
  • src/lib.rs:972-1002
    PropertyValue
    ;
    src/lib.rs:1197-1202
    PropertyInput
  • src/lib.rs:1232-1339
    NodeRef
    /
    EdgeRef
  • src/lib.rs:1888-1965
    PropertyProjection
    /
    ExprProjection
    /
    Projection
    (untagged)
  • src/lib.rs:2250-2323
    RepeatConfig
    ;
    src/lib.rs:1984-1993
    EmitBehavior
  • src/lib.rs:2327-2398
    IndexSpec
  • src/lib.rs:4041-4078
    BatchCondition
    ,
    BatchEntry
    ,
    NamedQuery
  • src/lib.rs:4089-4270
    ReadBatch
    /
    WriteBatch
    /
    BatchQuery
    (untagged)
  • src/lib.rs:4346-4452
    DynamicQueryRequestType
    (lowercase),
    DynamicQueryValue
    (untagged),
    DynamicQueryRequest
  • src/query_generator.rs:9-31
    QueryParamType
  • tests/register_metadata_tests.rs:182-186, 243-245, 274-275
    — ground-truth serialized examples
权威源码文件(当参考文档存在歧义时使用):
  • src/lib.rs:2506-2962
    Step
    枚举(所有变体)
  • src/lib.rs:1548-1596
    Predicate
    ;
    src/lib.rs:1603-1626
    SourcePredicate
  • src/lib.rs:1352-1384
    Expr
  • src/lib.rs:972-1002
    PropertyValue
    ;
    src/lib.rs:1197-1202
    PropertyInput
  • src/lib.rs:1232-1339
    NodeRef
    /
    EdgeRef
  • src/lib.rs:1888-1965
    PropertyProjection
    /
    ExprProjection
    /
    Projection
    (无标签)
  • src/lib.rs:2250-2323
    RepeatConfig
    ;
    src/lib.rs:1984-1993
    EmitBehavior
  • src/lib.rs:2327-2398
    IndexSpec
  • src/lib.rs:4041-4078
    BatchCondition
    ,
    BatchEntry
    ,
    NamedQuery
  • src/lib.rs:4089-4270
    ReadBatch
    /
    WriteBatch
    /
    BatchQuery
    (无标签)
  • src/lib.rs:4346-4452
    DynamicQueryRequestType
    (小写),
    DynamicQueryValue
    (无标签),
    DynamicQueryRequest
  • src/query_generator.rs:9-31
    QueryParamType
  • tests/register_metadata_tests.rs:182-186, 243-245, 274-275
    — 经过验证的序列化示例