Query 契约

query 是字段到条件的映射。多个字段默认使用 AND;需要显式逻辑组合时使用 $and$or

type QueryType = Record<string, QueryValue | QueryOperators> & {
  $and?: QueryType[];
  $or?: QueryType[];
};

基础等值

{
  "query": {
    "地区": "华东",
    "已付款": true,
    "数量": 10
  }
}

字段值与 { "$eq": value } 等价。null 表示空值等值语义。

比较 Operator

Operator含义典型值
$eq等于标量、日期、子查询
$ne不等于标量、日期、子查询
$gt大于数字、日期、可比较枚举
$gte大于等于数字、日期、可比较枚举
$lt小于数字、日期、可比较枚举
$lte小于等于数字、日期、可比较枚举
$in属于集合数组或单列子查询
$nin不属于集合数组或单列子查询
$exists是否存在/非空boolean
$regex正则匹配string
$contains包含string 或成员值
$recursive树形节点及后代根节点或递归配置
$and同一字段的条件全部成立条件数组
$or同一字段的条件任一成立条件数组

示例:

{
  "query": {
    "销售额": { "$gte": 1000, "$lt": 10000 },
    "渠道": { "$in": ["直营", "电商"] },
    "备注": { "$regex": "^重点", "args": { "options": "i" } },
    "删除时间": { "$exists": false }
  }
}

正则选项使用同级 args.options。旧版 $options 字段不再支持。

逻辑组合

Query 级组合

{
  "query": {
    "$or": [
      { "地区": "华东" },
      {
        "$and": [
          { "地区": "华南" },
          { "销售额": { "$gte": 10000 } }
        ]
      }
    ]
  }
}

$and/$or 的值必须是 Query 对象数组。

字段级组合

{
  "query": {
    "销售额": {
      "$or": [
        { "$lt": 0 },
        { "$gte": 10000 }
      ]
    }
  }
}

数组 Property

对于 isArray: true 的标量 Property,查询使用成员语义:

  • 直接值或 $eq:数组包含该成员;
  • $in:数组包含给定集合中的任一成员;
  • $ne:数组不包含该成员;
  • $nin:数组不包含给定集合中的任何成员。
{ "query": { "标签": { "$in": ["重点", "复购"] } } }

数组的物理存储和数据库支持取决于 Provider。

日期值

所有 primal_type: 'date' 的语义类型共享日期查询契约。

日期字符串

{ "日期": "2026-08-26" }

也可使用完整时间:

{ "时间": { "$gte": "2026-08-26 09:00:00" } }

绝对周期

{ "日期": { "year": 2026, "quarter": 3 } }

可用组成部分:yearquartermonthweekdayhourminutesecondperiodam/pm)。一个对象描述对应自然周期,并被展开为标准上下界。

相对周期

{ "日期": { "granularity": "month", "offset": -1 } }

granularity 可为 secondminutehourdayweekmonthquarteryearoffset 必须是整数。0 表示当前周期,-1 表示上一个周期,1 表示下一个周期。

旧式 { "$offset": { "month": -1 } } 不支持。

To-date Token

Token含义
DTD今日截至当前自然日结束
WTD本周至今
MTD本月至今
QTD本季度至今
YTD本年至今
{ "日期": "YTD" }

最新数据日期截断

相对或绝对周期展开后的上界超过当前日期时,系统会查询该数据源对应日期列的最新数据日期,并将上界限制在提问上界和最新数据周期末之间的较早值。该行为用于避免“本月/本年”结果错误包含尚未有数据的未来日期。

业务日历日期

业务日历值使用:

interface CalendarDateValue {
  calendar: string;
  key?: string;
  year?: number;
  quarter?: number;
  month?: number;
  week?: number;
  day?: number;
  relativeDay?: number | number[];
}

它先通过已配置的业务日历解析为自然日,再参与普通日期过滤。calendar 必填;其他字段按日历建模选择使用。

Object 关系查询

关系路径

推荐使用下划线路径:

{
  "query": {
    "客户_所属区域_名称": "华东"
  }
}

每一段 object Property 必须配置 ref,目标 Schema 必须可解析。

嵌套关系 Query

也可把关系条件写成嵌套形式:

{
  "query": {
    "客户": {
      "schema": "customers",
      "query": { "等级": "A" },
      "entity_id": "customer-1"
    }
  }
}

关系对象继承父 LogicForm 的版本,因此 version 可省略。schema 必须与 object Property 的 ref 一致。该形式会被规范化为关系路径条件。

子查询

Query 值可以是一个完整 LogicForm:

{
  "query": {
    "客户编号": {
      "$in": {
        "version": "2.0",
        "schema": "customers",
        "query": { "等级": "A" },
        "preds": [{ "pred": "编号", "name": "编号" }]
      }
    }
  }
}

契约:

  • 子查询必须只输出一列。
  • $eq$ne$gt$gte$lt$lte 使用标量子查询语义。
  • $in$nin 使用集合子查询语义。
  • 数组中的多个子 LogicForm 以集合合并。
  • 子查询中的每个完整 LogicForm 必须声明 version
  • 只能在数据库中表达的查询链路中使用;包含 JavaScript-only 计算的子查询会失败。

递归树查询

$recursive 查询一个根节点及其后代:

{
  "query": {
    "部门": {
      "$recursive": {
        "root": "dept-100",
        "includeSelf": true
      }
    }
  }
}

完整配置:

interface RecursiveQueryType {
  schema?: string;
  root?: QueryValue;
  roots?: QueryValue[];
  includeSelf?: boolean;
  idProperty?: string;
  parentProperty?: string;
}
  • 可直接把 $recursive 的值写成单个 root。
  • rootroots 二选一;至少提供一个根节点。
  • includeSelf 默认 true
  • object Property 默认从其 ref 推断树 Schema,否则使用当前 Schema。
  • idProperty 省略时,目标 Schema 必须恰好有一个 type: 'ID' Property。
  • parentProperty 默认使用 Schema 的 parentProperty,再回退到 pid
  • $recursive 不能与同一字段的其他 Operator 混用。
  • 当前由 MySQL、Doris、StarRocks 和 PostgreSQL Provider 支持。

可比较枚举

配置了 property.comparable 的 category 可以使用大小比较:

comparable: {
  values: ['低', '中', '高'],
  direction: 1,
}

查询值必须存在于 valuesdirection: 1 表示数组顺序从小到大,-1 表示从大到小。$min$max 和比较 Query 都使用这套业务顺序,而不是数据库字符串排序。

严格性规则

  • 未知字段、无效关系路径和未注册 Schema 会在执行数据库查询前失败。
  • Query 条件不会因为当前 Mapping 不支持而被丢弃;没有物理来源能够完整覆盖请求时会返回错误。
  • 不支持的 Query Operator 会失败,不会作为普通 JSON 静默传递。
  • 跨 Schema 条件通过关系路径、嵌套关系 Query 或子查询表达;跨 Schema 指标使用同一 LogicForm 的 preds[].schemapropertyResolve,不使用组合 LogicForm 输入。