LogicForm 契约

本页描述当前公开的 LogicForm V2 JSON 契约。

V2 的公开输入始终是一条 LogicForm 对象,不接受 LogicForm 数组或 logicforms 组合节点。执行器 可以为了跨 Schema 指标在内部拆分为多个计划,但拆分结果不是调用方需要构造的协议对象。

顶层结构

interface LogicformType {
  version: string;
  schema?: string;
  query?: QueryType;
  preds?: PredItemType[];
  groupby?: PredItemType[];
  sort?: Record<string, 1 | -1>;
  having?: QueryType;
  output?: { type: 'url' | 'data' | 'export' | 'sql' | 'sqlComponents'; filename?: string };
  limit?: number;
  limitBy?: number;
  page?: number;
  representation?: RepresentationType;
  entity_id?: string;
  from?: LogicformType;
  currency?: string;
}

字段说明

字段必填契约
version语义版本;当前最低为 2.0。关系查询沿用父节点版本,完整子查询必须声明自己的版本
schema物理查询必填逻辑 Schema 的 id;使用 from 的派生节点可省略
query行过滤条件,详见 Query 契约
preds输出字段或指标表达式
groupby分组键表达式
sort结果列名到 1(升序)或 -1(降序)的映射
having对聚合后的输出列进行过滤
output输出方式;当前执行入口仅支持 datasql
limit行数、结果比例或 -1
limitBy多维分组时每组保留的行数
page从 1 开始的页码,必须与有效 limit 一起使用
representation前端展示提示,不改变查询语义
entity_id实体身份快捷条件;placeholder 只保留上下文,不生成过滤
from以另一个完整 LogicForm 的结果作为当前输入
currency调用方约定的货币执行上下文

所有输入都会被复制,执行过程不会修改调用方传入的对象。

PredItem 表达式

predsgroupby 使用同一结构:

interface PredItemType {
  operator?: string;
  pred?: string | PredItemType;
  components?: PredItemType[];
  name?: string;
  schema?: string;
  args?: Record<string, unknown>;
  query?: QueryType;
}
字段说明
predProperty 名称/ID,或一个嵌套 PredItem
components多输入 Operator 的结构化操作数
operator已注册 Operator 名称;省略时表示直接选择 pred
argsOperator 配置,不用于存放结构输入
name最终输出列名;省略时按 locale 自动生成
query该指标自己的过滤条件,仅聚合 Operator 支持
schema省略时继承当前 Schema;在 preds 中可指定另一个已注册 Schema

同一 PredItem 不能同时声明 predcomponentsargs 必须是普通对象,name 必须是非空字符串。所有输出列名必须唯一。

直接字段

{ "pred": "门店", "name": "门店" }

单输入 Operator

{ "operator": "$sum", "pred": "销售额", "name": "销售额合计" }

嵌套 Operator

{
  "operator": "$abs",
  "pred": { "operator": "$sum", "pred": "利润" },
  "name": "利润绝对值"
}

多输入 Operator

{
  "operator": "$divide",
  "components": [
    { "operator": "$sum", "pred": "销售额" },
    { "operator": "$countDistinct", "pred": "订单号" }
  ],
  "name": "客单价"
}

默认输出

  • 同时省略 predsgroupby 时,默认输出当前权限允许的全部 Schema Property。
  • 显式提供 preds: [] 表示没有指标输出;如果也没有分组输出,请求会因空投影失败。
  • 当存在 groupby 时,结果列由分组输出与 preds 输出共同组成。

Groupby

普通字段可以直接分组:

{ "groupby": [{ "pred": "门店", "name": "门店" }] }

需要计算的分组键必须使用可生成数据库表达式的标量 Operator,例如:

{
  "groupby": [
    {
      "operator": "$dateBucket",
      "pred": "日期",
      "args": { "granularity": "month" },
      "name": "月份"
    }
  ]
}

聚合、窗口、复合查询和仅支持 JavaScript 的 Operator 不能作为分组键。数组 Property 直接分组时按成员展开,输出 Property 的 isArrayfalse

Having 与 Sort

having 引用最终输出列名:

{
  "having": { "销售额": { "$gte": 100000 } },
  "sort": { "销售额": -1, "门店": 1 }
}
  • having 只能引用聚合查询可见的输出。
  • sort 的 key 必须是输出列名,不能使用未输出的物理 Property。
  • JavaScript 后处理结果也可参与最终的 havingsort 和分页,但不能嵌入需要单条 SQL 的子查询。

分页

写法含义
limit: 20每页最多 20 行
limit: 0.2每页为总结果行数的 20%,按 ceil(total * 0.2) 计算
limit: 0返回 0 行
limit: -1不限制行数
page: 3第 3 页;页码从 1 开始

page 不能单独出现,也不能与 limit: -1 一起使用。旧字段 skip 已删除且不会自动换算。

limitBy 用于多维分组:当有两个或更多 groupby 时,按前 N-1 个分组键分区,每个分区保留 limitBy 行;保留顺序由 sort 决定。少于两个分组键时,limitBy 等价于普通 limit

派生查询 from

from 的结果成为外层 LogicForm 的字段空间:

{
  "version": "2.0",
  "from": {
    "version": "2.0",
    "schema": "sales",
    "groupby": [{ "pred": "门店", "name": "门店" }],
    "preds": [{ "operator": "$sum", "pred": "销售额", "name": "销售额" }]
  },
  "query": { "销售额": { "$gte": 10000 } },
  "preds": [{ "pred": "门店" }, { "pred": "销售额" }]
}

外层引用内层的输出名,不能绕过内层结果访问原 Schema 的其他字段。

跨 Schema 指标

跨 Schema 指标仍然属于同一个 LogicForm,放在根节点的 preds 中,并在 PredItem 上声明目标 schema。主 Schema 的查询和分组语义会被映射到目标 Schema;当两个 Schema 对同一实体粒度 使用不同的属性路径时,通过 propertyResolve 显式提供映射:

{
  "version": "2.0",
  "schema": "sales",
  "groupby": [{ "pred": "产品", "name": "产品" }],
  "preds": [
    { "operator": "$sum", "pred": "销售额", "name": "销售额" },
    { "schema": "targets", "operator": "$sum", "pred": "目标额", "name": "目标额" }
  ],
  "propertyResolve": {
    "targets": { "产品": "商品" }
  }
}
  • propertyResolve 的第一层 key 是目标 Schema id,第二层把主 Schema 的规范属性路径映射到目标 Schema 的属性路径。
  • 映射两端可以使用 Property idname;规范化后使用 canonical property path。
  • 主 Schema 的 querygroupby 会沿映射应用到各目标 Schema。无法解析或无法对齐时必须报错,不得静默忽略条件。
  • 目标 PredItem 的输入字段在其 schema 命名空间中解析;输出列名仍由 PredItem 的 name 决定,且必须全局唯一。
  • 执行器可以在内部拆分为多个 Provider 查询并按共享分组键合并结果;这是规划实现细节,不是新的 LogicForm 输入形状。

对象关系路径

primal_type: 'object' 且有 ref 的 Property 表示到另一个 Schema 的关系。使用下划线连接路径:

{
  "query": { "门店_城市": "上海" },
  "groupby": [{ "pred": "门店_城市", "name": "城市" }]
}

路径可用于 querygroupbypreds 和嵌套 Operator 输入。直接选择 object Property 时,结果返回填充后的实体对象,不是裸外键。

entity_id

entity_id 是单实体查询的快捷方式:

  • 普通 Schema 使用唯一的 type: 'ID' Property;
  • 层级 Schema 使用插件定义的 hierarchy.property
  • 若显式 query 已包含同一身份字段,以显式条件为准;
  • 值为 placeholder 时不生成数据库过滤,仅保留上下文。

Representation

支持的展示提示值为:

valuetablepiebarcolumnstackedColumnlinescatterareabubblefunnelguageheatmaphistogramparetoradartreemapwordCloudmapentityreporttextvideosimages

该字段只作为调用方和前端之间的展示元数据,不影响筛选、聚合或 SQL。