物理表达式(Physical Expression)
物理表达式(physicalExpression)是属性(Property)上的一个可选高级配置项,用于描述从物理存储格式到查询可用格式的转换规则。它对应源码 OntologyProperty.java 中的 physicalExpression 字段。
使用场景
在真实业务系统中,物理表中存储的列值往往不是"干净"的、可以直接拿来做语义计算或展示的值,常见的情况包括:
- 货币字段带有符号或千分位分隔符,例如
"$1,234.56" - 字符串字段两端存在多余空格或不可见字符
- 编码字段需要做简单的清洗或归一化处理后才能在语义层中使用
如果不做处理,这些"脏数据"会直接影响 Ontology 之上的统计、筛选与展示效果。物理表达式机制允许在不修改物理表结构、不侵入 ETL 流程的前提下,在语义层声明一段转换逻辑,使该属性在被查询、聚合或展示时,自动应用这段转换。
工作原理
物理表达式本质上是一段 SQL 表达式片段,使用 {col} 作为列名(或带表别名的列引用)的占位符。系统在生成实际查询时,会将 {col} 替换为该属性实际绑定的物理列引用,并把替换后的表达式嵌入到生成的 SQL 中。
对应源码逻辑(OntologyProperty.java):
/**
* 物理表达式(可选):用于描述从物理存储格式到查询可用格式的转换。
* 使用 {col} 作为列名占位符。
* 示例:REPLACE(TRIM({col}), '$', '') - 清洗货币符号
*/
public String physicalExpression;
/**
* 判断是否需要物理层转换
*/
public boolean needsPhysicalTransform() {
return StringUtils.isNotBlank(physicalExpression);
}
/**
* 应用物理转换(替换 {col} 占位符)
*/
public String applyPhysicalTransform(String columnRef) {
if (!needsPhysicalTransform()) {
return columnRef;
}
return physicalExpression.replace("{col}", columnRef);
}
可以看到:
- 当
physicalExpression为空时,属性按照原始列直接参与查询,不做任何转换; - 当
physicalExpression不为空时,{col}会被替换为实际的列引用(例如p.Product_Price),生成最终参与查询的表达式。
配置示例
假设某个 ObjectType 对应物理表中存在一个名为 Product_Price 的列,其中的值带有美元符号与千分位分隔符(如 "$1,234.56"),希望在语义层中将其作为纯数值参与计算,可以在该属性的物理表达式中填写:
REPLACE(TRIM({col}), '$', '')
当系统生成查询时,{col} 会被替换为实际列引用,最终生成类似如下的表达式片段:
REPLACE(TRIM(p.Product_Price), '$', '')
物理表达式中必须包含 {col} 占位符,系统在拼接 SQL 时会原样替换该占位符为目标列的引用。如果表达式中不包含 {col},则该转换片段不会与实际列产生关联,可能导致生成的 SQL 不符合预期。
字段位置与表单行为
在添加 / 编辑属性的表单中,物理表达式属于高级(advance)配置项,默认收起,需要展开"高级设置"后才能看到并填写,输入控件为多行文本框(TEXTAREA),不做强制校验(即该字段可以留空)。

与其他属性配置的关系
- 物理表达式是列级的转换声明,作用范围仅限于该属性自身,不影响 ObjectType 上的其他属性;
- 物理表达式与属性的语义角色(roleType)是相互独立的两个配置维度:物理表达式解决"取值是否干净"的问题,语义角色解决"这个属性在语义上扮演什么角色"的问题,两者可以同时配置;
- 当属性同时设置了共享对象(Shared Property)或值类型(Value Type)关联时,物理表达式仍然作用于当前属性自身的物理列,不会被关联对象上的配置覆盖。