Skip to content

QM 定义参考

本文面向需要编写或审查 Foggy Query Model(QM)的开发者,按定义对象和属性组织当前公开查询模型契约。TM 定义请参考 TM 定义参考,运行时查询语法请参考 JSON Query DSL 语法参考

QM 是面向 LLM、应用和工具协议的查询契约。它基于一个或多个 TM,选择对外暴露的字段,定义计算字段、默认排序、预定义条件和治理规则。DSL 查询只能引用当前 QM 暴露的语义字段,而不是任意 TM 字段或数据库物理列。

1. QM 文件结构

QM 文件导出 queryModel 对象。

javascript
const fs = loadTableModel('FactSalesModel');

export const queryModel = {
    name: 'SalesAnalysisQueryModel',
    caption: '销售分析',
    model: fs,

    columnGroups: [],
    orders: [],
    conds: [],
    accesses: []
};

1.1 queryModel 顶层属性

属性类型必填说明
namestringQM 唯一标识
captionstring显示名称
descriptionstring查询模型语义描述
modelobject关联的主 TM,通常为 loadTableModel 返回值
joinsarray多模型 QM 的显式关联定义
loaderstring加载器版本
dataSourceobject宿主注入的数据源对象;公开模型通常使用 TM 的 dataSourceName
columnGroupsarray查询字段分组
ordersarray默认排序
condsarray预定义查询条件
accessesarray行级权限或查询增强规则
memberPermissionsarray覆盖 TM 维度成员权限
aiobject查询模型级 AI 元数据配置
deprecatedboolean是否废弃
extDataobject自定义扩展元数据

2. 模型绑定

2.1 单模型绑定

javascript
const fo = loadTableModel('FactOrderModel');

export const queryModel = {
    name: 'FactOrderQueryModel',
    model: fo,
    columnGroups: []
};

2.2 多模型绑定

javascript
const fo = loadTableModel('FactOrderModel');
const fp = loadTableModel('FactPaymentModel');

export const queryModel = {
    name: 'OrderPaymentQueryModel',
    model: fo,
    joins: [
        fo.leftJoin(fp).on(fo.orderId, fp.orderId)
    ],
    columnGroups: []
};
属性类型必填说明
modelobject主 TM 的 loadTableModel 返回值
joinsarrayleftJoin / innerJoin / rightJoin 等构造的关联定义
onfunction指定关联字段,可链式追加 .and(...)

joins 是当前推荐的多模型 QM 写法。onBuilder 仍可作为 TM dimension 的高级自定义关联条件使用,但不建议作为新 QM 多模型绑定的主要示例。

3. 列组与列项

columnGroups 决定 QM 对外暴露的查询字段。只有进入 columnGroups.items 并通过治理规则的字段,才应被视为 DSL 可引用字段。

javascript
columnGroups: [
    {
        caption: '指标',
        items: [
            { ref: fs.salesAmount },
            {
                name: 'profitRate',
                caption: '利润率(%)',
                formula: 'profitAmount / salesAmount * 100',
                type: 'NUMBER'
            }
        ]
    }
]

3.1 columnGroup 属性

属性类型必填说明
captionstring列组显示名称
itemsarray列项列表

3.2 column item 属性

属性类型必填说明
refobject/string否¹TM 字段引用,推荐使用 loadTableModel 返回的字段引用
namestring否¹输出字段名或计算字段名
captionstring覆盖显示名称
descriptionstring字段说明
aliasstring输出别名
formulastringQM 计算字段公式
typestring计算字段返回类型
partitionBystring[]窗口函数分区字段
windowOrderByobject[]窗口函数排序字段
windowFramestring窗口帧定义
emptyDefaultany计算字段为空时的默认值,常用于 COALESCE
aiobjectAI 元数据配置

¹ 普通字段通常使用 ref;计算字段通常使用 name + formula

4. 字段引用

QM 中通常通过 loadTableModel 的代理对象引用字段。

引用说明
fs.orderIdTM 属性
fs.salesAmountTM 指标
fs.customer维度引用,通常展开为 $id$caption、维度属性和嵌套维度;显式列会避免重复输出
fs.customer$caption维度显示值
fs.customer$customerType维度属性
fs.product.category$caption嵌套维度属性

响应列名中,嵌套维度路径里的 . 通常转为 _

QM 引用响应列名
fs.product$captionproduct$caption
fs.product.category$captionproduct_category$caption
fs.product.category.group$captionproduct_category_group$caption

DSL 请求应使用当前 QM 暴露的最终字段名。例如当前 QM 暴露 product_category$caption 时,DSL 中应引用 product_category$caption,而不是物理列名或未暴露的 TM 内部路径。

5. 默认排序与预定义条件

5.1 orders

javascript
orders: [
    { name: 'salesDate$caption', order: 'desc', nullLast: true }
]
属性类型必填说明
namestring否¹排序字段名
refobject/string否¹排序字段引用,支持 loadTableModel 字段引用或字符串
orderstringascdesc
nullLastboolean空值排在最后
nullFirstboolean空值排在最前

¹ nameref 至少提供一个;同时提供时以 ref 为准。

5.2 conds

conds 用于描述查询条件元数据,常用于 UI 或工具侧展示可筛选字段。

属性类型必填说明
namestring条件名称
fieldstring对应查询字段
columnstring对应物理列
typestring条件类型
queryTypestring默认查询操作符

常见 typeDICTDIMBOOLDATE_RANGEDAY_RANGECOMMONDOUBLEINTEGER

6. 权限与治理属性

语义层治理分为 QM 文件内声明和宿主运行时注入两类。QM 文件负责声明静态模型契约;用户、公司、物理列黑名单等上下文通常由宿主系统在调用查询时注入。

6.1 accesses

QM 的 accesses 用于在查询构建阶段注入治理规则,例如行级过滤、租户边界或业务范围限制。

javascript
accesses: [
    {
        queryBuilder: (context) => {
            const query = context.query;
            query.and(fs.companyId, context.securityContext?.companyId);
        }
    }
]
属性类型说明
dimensionstring维度名,用于声明维度级访问规则
propertystring属性名,用于声明属性级访问规则
dimensionDataSqlfunction维度数据权限 SQL 生成函数
queryBuilderfunction接收 context,在查询构建阶段注入条件
context.queryobject查询构建器
context.securityContextobject安全上下文
context.requestobject原始查询请求

权限规则在引擎侧执行,不依赖 LLM 自行遵守提示词。

6.2 运行时治理参数

运行时治理参数通常不直接写入 .tm.qm 文件,而是由 MCP 服务、应用 API、Odoo Bridge 等宿主在查询请求上下文中注入。

参数说明
fieldAccessQM 字段白名单;为空列表表示无字段可见,null 表示不启用字段白名单
deniedColumns物理列黑名单,用于阻止查询访问指定表列
systemSlice系统强制过滤条件,如公司、租户、组织范围
securityContext当前用户、公司、角色等宿主安全上下文

LLM 不应自行构造或覆盖这些安全参数。Compose Script 和 DSL 查询应使用宿主暴露的受限 API,由引擎合并治理上下文并生成最终查询。

6.3 memberPermissions

QM 可通过 memberPermissions[] 覆盖 TM 维度上的 memberPermission,用于某个查询模型需要更窄的成员可见范围时使用。

javascript
memberPermissions: [
    {
        dimension: 'product',
        patch: {
            visibleColumns: ['id', 'caption'],
            forcedSlice: [
                { field: 'enabled', op: '=', value: true }
            ]
        }
    }
]
属性类型说明
dimensionstring被覆盖的 TM 维度名
patchobject静态成员权限补丁
queryBuilderfunction动态成员权限构建函数

patch.visibleColumns 控制成员查询返回字段;patch.forcedSlice 注入强制过滤;patch.forcedOrderBy 注入强制排序;patch.hierarchyEnabledpatch.allowedHierarchyOps 控制层级成员操作范围。QM 中的成员权限用于覆盖或收窄 TM 维度上的默认成员权限。

7. 命名规则

对象建议命名示例
QM 文件{QueryModelName}.qmSalesAnalysisQueryModel.qm
QM namePascalCaseSalesAnalysisQueryModel
字段 namecamelCasesalesAmount
维度属性引用$ 分隔customer$caption
嵌套维度响应字段_ 连接路径段product_category$caption

8. 与 DSL 的关系

QM 定义字段集合和治理边界;JSON Query DSL 在运行时引用这些字段。

QM 暴露字段DSL 引用
TM property order_id -> orderId"orderId"
TM measure sales_amount -> salesAmount"salesAmount"
dimension customer.captionColumn"customer$caption"
dimension property customer_type"customer$customerType"
QM calculated field profitRate"profitRate"

查询 DSL 语法见 JSON Query DSL 语法参考