业务特殊逻辑配置
功能介绍
业务特殊逻辑配置(enrich)是在语义层专家模式中配置的一个函数,作用是开发特殊业务逻辑。当用户提问后,系统会将问题转换为 Logicform,如果有业务特殊的逻辑需要添加,就可以通过 enrich 功能修改,返回一个新的 Logicform。
enrich 功能的使用需要有 JavaScript 基础。
场景举例
以下场景都比较适合使用 enrich 功能:
- 你希望当提问者问到【上个月业绩】的时候,这个【上个月】指的是上上个月的 28 号~上个月的 27 号。
- 你希望当提问者问到【商品销售额】的时候,默认加上【是否退货 = false】,但是其他场景下,不要加上此条件。
总结来说,遇到需要逻辑判断的特殊业务规则,都可以用 enrich 功能实现。
使用方式
在 系统搭建 → 语义建模 → Schema 列表 → 点击具体 Schema → 业务逻辑定制 处打开。
业务特殊逻辑配置(enrich) 本质是一个函数。以下是该函数的签名:
该函数接受 3 个参数,分别是:
- logicform: 代表用户的提问意图。可直接在 logicform 上进行修改。
- normedLogicform: 规范化后的 logicform,方便用于各种 if 条件判断。尤其是关于日期,logicform 变量
- helperFunctions: 一些帮助函数,典型的有 moment。可以用如下形式调出 moment
将 logicform 修改后,直接返回 logicform 即可。
注意:enrich 函数也支持 async 版本,只要在函数开头写上 async 就好
helperFunctions 里面所有支持的函数
常用函数:
- moment: momentjs 库
- _: underscore 库
- execute: logicform 的 execute 函数。和自定义指标里面 execute 是一样的。
- getGranuality: 传入日期参数,如
{$gte:'xxx', $lte: 'xx'},返回日期的粒度,如year、month、day。 - isDimensionInQuery:
(query: object, dimension: string)。返回true/false,判断某个 query 里是否包含指定维度。 - isDimensionInLogicform:
(logicform: LogicformType, dimension: string)。返回true/false,判断整个 logicform 里是否包含指定维度。 - getQueryWithKey:
(key: string)。查找 logicform 中所有包含指定字段名的 query 节点,适合批量修改时间条件、业务条件等。
可用上下文:
- graph: 当前解析过程中的 graph 对象。
- schemas: 当前可用的 schema 集合。
- customFunctions: 当前加载的自定义函数集合。
- locale: 当前语言环境。
- schema: 当前 schema 的 enrich 中可用。
- renamePredItem: 当前 schema 的 enrich 中可用,用于重命名
predItem。
此外,helperFunctions 还会透出一部分 Logicform.util 中的工具函数。不同版本里可用项可能略有差异,实际请以运行环境为准。
详细说明
moment
moment 是标准的时间处理库,可用于日期计算、格式化、偏移和区间处理。
适合场景:
- 计算相对日期,例如上个月、近 7 天、最近一个完整财月
- 对日期进行格式化,例如输出为
YYYY-MM-DD - 做日期偏移,例如加减天、月、年
使用示意:
_
_ 是 underscore 工具库,适合做数组、对象的遍历、过滤、分组和转换。
适合场景:
- 批量处理
groupby、preds、query中的字段 - 做简单的数据整理和条件筛选
execute
execute 是 logicform 的执行函数,可以在 enrich 过程中执行一个 logicform,拿到查询结果后再继续改写当前 logicform。
函数特征:
- 支持
async enrich - 适合”先查一遍,再决定怎么改 logicform”的场景
使用时需要注意:
- 这类写法会在 enrich 阶段额外执行查询
- 如果逻辑复杂或调用频繁,要注意性能影响
getGranuality
getGranuality 用于判断一个日期 query 的粒度。
函数签名如下:
典型返回值包括:
yearquartermonthday
适合场景:
- 先判断用户问的是按年、按月还是按天,再决定 enrich 逻辑
isDimensionInQuery
isDimensionInQuery 用于判断某个 query 对象里是否出现了指定维度。
函数签名如下:
适合场景:
- 只想判断某一段 query,而不是整个 logicform
- 结合
$and、$or结构做更细粒度判断
isDimensionInLogicform
isDimensionInLogicform 用于判断整个 logicform 中是否包含某个维度。
函数签名如下:
适合场景:
- 如果用户问到了某个维度,就追加特定业务规则
- 根据是否存在某个维度,选择不同的查询口径
使用示意:
getQueryWithKey
getQueryWithKey 用来在当前 logicform 中递归查找所有包含某个字段名的 query 节点。
这个函数适合以下场景:
- 你需要找到所有包含某个字段的筛选条件,例如
日期 - 这个字段可能出现在主
query、preds[].query、from.query,甚至更深层的$and、$or条件里 - 你希望批量修改这些 query,而不是只处理某一个固定位置
函数签名如下:
参数说明:
key: 要查找的字段名,例如日期
返回值说明:
- 返回一个数组
- 每一项都表示一个命中的 query 节点
queryFromLogicform: 原始logicform中命中的 query 对象,可直接修改queryFromNormed: 对应的规范化 query 对象,适合配合条件判断使用
使用示意:
完整示例可参考财年场景解决方案,其中使用 getQueryWithKey('日期') 批量找到所有日期条件,并改写为财年日历查询。
renamePredItem
renamePredItem 用于重新生成或覆盖某个 predItem 的名称。这个能力通常只在 schema 级 enrich 中可用。
函数签名如下:
适合场景:
- 你修改了某个指标或谓词的结构,想同步更新它展示给用户的名称
- 你新增了衍生
predItem,希望它有可读名称
graph / schemas / customFunctions / locale / schema
这些不是函数,而是 enrich 执行时注入的上下文对象。
常见用途:
graph: 读取当前图解析上下文schemas: 获取全部 schema 定义customFunctions: 获取当前自定义函数locale: 根据语言环境做差异化逻辑schema: 获取当前 schema 的定义,只在 schema 级 enrich 中可用
完整使用示例
以下是一个医院满意度调查场景的真实案例,展示了如何根据用户问题的维度组合,动态追加筛选条件。
背景
某医院使用 Data Agent 分析患者满意度数据,其中:
- 医生 是一个维度字段,用户可以按医生筛选或分组
- 十分满意度 是一个自定义指标,计算公式为评分≥10 分的问卷数 / 总问卷数
- 科室 是一个维度字段
- 问题类型 是一个分类字段,也是本次需要根据不同条件设置不同逻辑的字段
业务需求
- 当提问涉及「医生」+「十分满意度」指标时,自动限定数据范围为「问题类型 = 医生」(即只看医生相关的满意度条目)
- 当科室为「医美中心」时,问题类型需要进一步细分为「外科医生」或「皮肤科医生」,并覆盖上一条的默认规则
完整代码
效果对照
要点总结
核心思路:先判断,再修改
整个 enrich 函数的本质就是 「在什么条件下,修改什么」。写 enrich 之前,先把业务规则转换成下面这个模板:
当用户问题中同时出现 A 和 B,则追加筛选条件 C;但如果出现了 D,则把 C 替换为 E。
上例中:
- A = 问到了「十分满意度」指标
- B = 筛选或分组的维度包含「医生」
- C = 追加
"问题类型": "医生" - D = 科室为「医美中心」
- E = 覆盖为
{"$in": ["外科医生","皮肤科医生"]}
判断维度的三种方式
根据用户问题中维度出现的位置,判断方式不同:
用 item.operator 判断自定义指标,用 item.pred 判断 Schema 原生字段(如 item.pred === "amount")。两者不可混用。
理解"何时触发修改"
enrich 的核心价值在于只在特定条件下才干预 logicform,而不是对所有问题都无差别修改。判断条件可以从以下角度考虑:
-
指标条件 — 只有问到了特定指标才触发(如上例中的「十分满意度」)。通过
logicform.preds判断,避免影响无关问题的查询结果。 -
维度条件 — 只有涉及特定维度才触发(如上例中的「医生」)。可以同时检查 query 和 groupby,确保不遗漏「按某维度分组」这种问法。
-
值条件 — 当某个字段的值为特定内容时才触发(如上例中科室名称 == "医美中心")。通过访问深层嵌套的 query 结构来判断。
-
组合条件 — 用
&&(且)和||(或)组合以上条件,精确控制触发范围。例如上例的:含义:指标必须匹配,且维度在筛选或分组中至少命中一个。
理解"修改的优先级"
当一条 enrich 函数里有多条规则时,代码的书写顺序决定优先级:
上例中规则2在规则1之后,因此当科室 = 医美中心时,规则2的赋值会直接覆盖规则1的赋值。如果反过来写,规则1就会错误地覆盖规则2的细分结果。
- 先写通用规则(覆盖面广的),再写特殊规则(覆盖面窄但优先级高的)
- 每条规则用注释标明「什么条件下触发」,方便后续维护
- 用
$in运算符表示「多选一」,比写多个$or更简洁

