Logicform 基础结构
Logicform 采用 JSON 结构描述一条查询请求。接口定义可在 semanticdb-core/src/logicform/logicform.ts 中找到,核心内容如下:
其中 PredItemType、GroupbyItemType、QueryType 等结构都会在后续章节单独说明。
字段与 SQL 的对应
from 子查询
from 用于表达“当前查询基于一个子 Logicform 的结果继续查询”。它和 query 中的子查询区别在于:
示例:
这个结构表达的是:先在内层得到“年初至今销售额超过 100 万的地区”这个中间结果,再由外层对这些结果做计数。
如果用 SQL 来类比,可以理解为:
另一个常见理解方式是:from 适合表达“先筛一层中间表,再对中间表继续做聚合、排序或分页”,而不是只把普通 WHERE 条件搬到外层。
Having 子句
having 用于对聚合后的结果进行过滤,与 SQL 的 HAVING 子句对应。它与 query 的主要区别在于:
基本示例
筛选销售额超过 100 万的地区:
对应的 SQL:
复杂条件
having 支持与 query 相同的操作符:
与 query 的组合
执行顺序:
query过滤 2024 年的数据- 按
地区分组并计算销售额 having过滤销售额 > 100 万的地区
跨表字段路径
在 Logicform 中,query 的 key、groupby._id、pred.pred 等位置都可以使用带下划线的字段路径,例如 产品_品类、门店_地理位置、物料_品牌_品类。
这里的 _ 不是普通字符串拼接,而是表示沿着 schema 的引用链逐级跨表取字段。可以把它理解为:
门店_地理位置:先从当前 schema 关联到门店,再从门店关联到地理位置物料_品牌_品类:先到物料,再到品牌,最后取品类
示例:
这类路径是否能解析成功,取决于语义层中是否已经配置好对应 schema 之间的引用关系。若引用链存在,执行器会根据该链路自动生成 JOIN。
推荐理解规则:
query中用_:表示按跨表字段筛选groupby._id中用_:表示按跨表维度分组pred.pred中用_:表示引用跨表字段做指标计算
如果某条路径在语义层里不存在对应引用关系,即使字段名写对了,也无法正确执行。
实体唯一性
entity_id 用来表达“某个实体位点已经指向一个具体实体”。它的核心作用是保证实体唯一性,避免把同名实体错误地聚合在一起。
例如,用户提问“张三今年业绩”。“业绩”通常来自事件表,而 entity_id 则应出现在实体 schema 对应的子查询里,而不是直接挂在事件表根节点上。
这里的 entity_id: "E001" 表示 员工 这个实体位点已经被唯一定位到 ID 为 E001 的那个“张三”,因此不会把其他同名员工一起聚合进来。
如果当前阶段还不知道具体的实体 ID,也可以写成:
entity_id = "placeholder" 的作用不是提供真实 ID,而是向系统表达“这里是一个实体位点,不能把多个同名实体聚合在一起”。后续即使没有完成实体消歧,系统也应该保留“这是单个实体”的语义,而不是退化成同名实体汇总。
因此可以把它理解为一条规则:
entity_id应该出现在实体 schema 的节点上- 事件表、明细表、事实表根节点通常不直接携带
entity_id
除了实体唯一性之外,在某些带层级编码的 schema 中,entity_id 还可能被执行器用于粒度判断。
货币上下文
currency 用于声明当前 Logicform 的货币上下文。它通常出现在涉及金额、汇率换算或跨币种展示的场景中。
如果未显式指定,默认值为 CNY,会参与金额换算。
书写约定
- Logicform 必须是一个合法的 JSON 对象。结构字段使用英文键名,例如
schema、preds、query、groupby。 - 业务字段名通常出现在
query的 key、groupby._id、pred.pred等位置,这些名称直接来自语义建模,可为中文。 - 嵌套结构主要出现在
query中的子 Logicform、pred中嵌套PredItemType、以及from中的子 Logicform,而不是所有字段都任意嵌套。
了解了整体框架后,可以继续阅读:
- 指标(Pred):如何编写指标及常见算子。
- 筛选(Query):MongoDB 风格的条件表达。
- 分组(Groupby):维度分组与层级。
- 排序与分页:返回顺序控制。

