业务术语表¶
业务术语表是覆盖在你的数据模型之上的一套活的词汇。语义层中的每一个物理列都会解析到一个术语——只要多个列承载同一个概念,无论拼写差别多大,它们都归到同一个共享术语。每个术语可以持有一条定义、一组指向其他术语的带类型关系,以及一份掌握该含义的主题专家名单。
那套共享词汇就是业务语言与物理数据之间的桥梁。一个知道"customer"命名了每一个承载客户标识符的列的 AI 智能体,无需猜测 cust_id、customerId 和 CUSTOMER_KEY 中哪一个才对——它们全都解析到同一个术语,而术语带着定义。
术语如何推导¶
Provisa 使用一条确定性的规范化规则(REQ-1387),自动从每个列名推导出一个术语:大小写折叠、分隔符与 camelCase 分词、缩写展开,以及尾部代理令牌的剥除。
缩写展开把常见的企业简写映射为完整形式:cust → customer、txn → transaction、qty → quantity,依此类推。id 和 key 都展开为 identifier。该对照表是固定且保守的——像 st、min、no 这类含义不明的简写保持原样,而不是猜错。
代理令牌剥除会移除尾部的 identifier、code、index 或 reference 令牌。名为 cust_id 的列并不是在命名标识符本身;它是在通过一个代理值命名一位客户。剥掉代理后,cust_id 和 customerId 都落到术语 customer 上。只有尾部令牌会被剥除,并且绝不剥掉最后剩下的那个令牌:一个光秃秃的 id 列展开为 identifier 并就此打住。
去重才是关键。规范化规则是确定性的,因此 cust_id、customerId 和 CUSTOMER_KEY 全都产出 customer。每个列在唯一得出的那个术语上获得一条 ref,而不是产生三个各自独立的术语。这样一来,人工整理只需在一个地方补上定义,而不是三个。
通用短语¶
有些规范化后的短语过于通用,本身构不成一个概念。一个光秃秃的 name、date 或 identifier 列命名的是其所在表那个概念的一项属性,而不是独立于该表的概念。员工有名字;产品也有名字;它们不是一回事。
当某个短语落入通用集合且存在可用的表上下文时,术语会被限定为 <表概念> <短语>:employees.first_name 规范化为 employee first name,而 orders.id 规范化为 order,因为随后的代理剥除把被限定的短语坍缩到它所标识的那个概念上。最后这种情形很重要:orders 的主键以及其他表上的每一个外键 order_id 全都落到 order 上,无需任何额外的人工整理。
通用集合涵盖属性名词(name、date、status、type、amount、quantity)、审计轨迹短语(created_at、modified_by、submitted_timestamp),以及另外几个几乎出现在每张表上的短语。
业务名称,而非物理名称¶
推导出的术语沿用列的业务名称——建模者设置了别名时用别名,没设置时用物理名称(REQ-1581)。当 usr_nm 被取别名为 user name 时,推导出的术语就是 user name,而不是 user number 或对 usr_nm 的某种展开。
给列取别名是更有力的更正。别名会传到读取该列的每一个界面——SQL、GraphQL、AI 智能体、目录——因此模型在各处都能正确地自我描述。而重命名术语只修好一条目录条目,把仍写着 usr_nm 的列留给下一个读者。UI 中的提议术语横幅直接这么说:先给列取别名;只有当列名没问题、有问题的是词汇时,才重命名术语。
给列重新取别名会重新推导它的提议术语,因此术语表跟着模型走,而不是要求你把同一处更正做两遍。一旦整理者为某个术语补上了定义、关系或专家,别名的改动就不会再移动那条 ref——那份工作属于整理者,会被保留。
访问路径式的表名¶
有些表名描述的是一条访问路径而非一个概念:user_by_name 是通过名称查找到达的用户,而不是另一种实体。当 Provisa 为通用短语的限定推导表概念时,会在连接词处切断表名(REQ-1582)。user_by_name 变成 user;orders_by_customer 变成 order。
不做这个切断的话,user_by_name 上的代理键会规范化为 user name,并与真正的 users.name 属性相撞——一个术语同时装着一个事物和它自己的一个字段。该切断只作用于表概念。在列名中,by 是复合名词的一部分:pet_by_name 和 pet_name 规范化到同一个术语 pet name。
什么样的术语算已整理¶
由列名规范化而生的术语一开始是空白的——是一项提议,还算不上词汇。只要满足以下任意一条,它就成为已整理:
- 已保存一条定义。
- 已添加一条关系边。
- 已指派一位主题专家。
- 整理者已手动将其停用。
整理与否关系到术语的生命周期。当一个已整理术语的最后一个物理列从模型中移除时,该术语会被弃用而不是删除:它退出服务,保留编辑者提供的内容,并在同一个列重新出现时自动复活。未整理且不再有列的术语则直接被移除。
从表重新同步¶
每当一张表被保存或重新加载,sync_table_refs 都会把该表的列与既有的 ref 对账。新列会创建或链接术语;离开的列会撤下其 ref;而移除或弃用规则会为任何失去最后一条 ref 的术语作出裁定。
重新推导只针对未整理的术语。如果你给某个列取了别名、提议术语因而改变,ref 就会移到新术语上。如果该术语已整理,链接保持不动——别名的改动没有推翻整理者对术语的选择。
一个抽象术语,若它通往物理数据的唯一路径要穿过某个正在离开的术语,则它会被弃用而非移除,从而在重新接线之前保住概念结构。
关系¶
术语通过带类型的边与其他术语建立关系。受支持的关系类型有:
| 类型 | 含义 |
|---|---|
KIND_OF |
源术语是目标术语的一种。 |
PART_OF |
源术语是目标术语的一个组成部分。 |
SYNONYM_OF |
这两个术语在本领域中可以互换。 |
RELATED_TO |
一种松散的关联——没有更强的说法适用。 |
VALID_VALUE_OF |
源是目标枚举或域的一个允许值。 |
DERIVED_FROM |
源是由目标计算或取得的。 |
REPLACES |
源取代了已弃用的目标。 |
PREFERRED_TERM_FOR |
相对于不推荐的目标,源是首选术语。 |
TRANSLATION_OF |
源是目标的某个区域或语言的译法。 |
ANTONYM_OF |
源在语义上与目标相反。 |
关系是有方向的。UI 会同时展示出边(本术语 → 另一术语)和入边(另一术语 → 本术语),并为每个方向标注各自的白话短语。
这些边存放在 glossary_term_edges 中,这是一张声明为联结(junction)关系的关联表(REQ-1586):它的 rel_type 列是判别列,因此上表中的每种类型都是两个 GlossaryTerm 节点之间独立的 Cypher 关系类型,而不是具体化节点上的一个属性。该表随元数据模式的其余部分一并置备,在图客户端中不显示为节点——它就是边。它没有任何专属于业务术语表的地方:它的声明方式与你在自己的表上声明联结完全相同,并且由同一套代码读取。
[tool-verified: provisa/cypher/label_map.py:378-397, provisa/api/startup_seed.py:508-550]
抽象术语¶
抽象术语自身没有物理列 ref。当一个业务概念横跨多个具体术语时,就用一个抽象术语——一把伞,你随后把它接到那些确实持有列的具体术语上。举例来说,revenue 可以是抽象的,由 order amount、adjustment amount 和 refund amount 发出的 PART_OF 边指向它。
一个通过关系图无法到达任何物理列的抽象术语,是一项悬空的提议。它不会出现在智能体的术语搜索中,也不会出现在元数据导出里——一个没有命名任何数据的术语回答不了任何问题。
面向消费界面的准入规则¶
消费界面可以提供的术语必须满足三个条件(REQ-1387):
- 在役——未被停用(整理者将其撤出服务)且未被弃用(它失去了最后一个列,只是因为删掉它会留下悬空的东西才被保留)。
- 有定义——它带着一条定义。由列名推导出的术语是一个令牌,而不是一层含义。没有定义,它就是一项等待整理者的提议,绝不是智能体可以据以立论的词汇。
- 落地——经由在役术语,连通到至少一个持有物理列 ref 的术语。术语表是进入数据的入口,因此每条链条都必须终结于某个列。
连通性会在图中传播:抽象术语通过任何一个已到达数据的在役邻居到达数据。退役的术语不导通——一个已停用的术语不会让依赖它的术语继续存活。
元数据导出¶
作为元数据导出的一部分,术语表会发布到外部数据目录。同一条准入规则适用,只是收窄了一处:术语是否落地,仅对照那些确实会发布的列来判定。若某个术语的列全部被排除在导出之外——因为它们所在的表未被标记为数据产品,或因为技术性过滤器将其排除——那么就导出而言它不算落地,即便它在控制平面中持有 ref。
关系边只在两个端点术语都发布时才发布。
列资产是独立导出的。某个术语被排除,并不会隐藏其底层数据。
把术语排除在导出之外¶
有些列承载的是管道设施而非业务数据:ETL 批次标识符、行版本、摄取时间戳。由这类列推导出的术语可能有一条完全准确、却根本算不上业务词汇的定义(REQ-1583)。从元数据导出中排除这一控件会把该术语,以及任何以它为终点的关系边,从 Provisa 发布的目标目录中扣下,而列本身仍会作为资产导出。
判据是业务是否说这个词,而不是定义好不好。ETL 批次标识符有明确的含义,属于给工程师看的术语表;它不属于业务目录里 customer 和 revenue 的旁边。
使用术语表¶
在 UI 中打开管理 → 术语表。左侧面板列出每一个术语;点击其中一个即可打开它的详情视图。从那里你可以:
- 重命名术语,在不移动其列的前提下改变措辞。
- 添加定义,可以自己敲一条,也可以点击 AI 起草按钮,依据术语的名称、它的物理列及其关系生成一个起点。草稿在你确认之前不会保存。
- 移动 ref以合并两个术语:在任一物理 ref 旁的下拉菜单中挑选目标术语。若源术语因此失去最后一条 ref,会自动按移除或弃用规则作出裁定。
- 添加关系,在本术语与另一术语之间建立关系,类型从封闭集合中选取。对既有的边应就地改类型,而不是删掉再加一遍。
- 指派专家,按用户 ID 指派,种类为
expert或author。 - 停用术语,使其退出服务。它保留自己的列,在这里仍可编辑,但智能体的术语搜索和元数据导出都会跳过它。若该概念日后回归,可以再恢复它。
- 批量生成定义,一次性填满所有空白定义。只写入空的定义;人写的文字绝不会被覆盖。
- 批量生成关系,在完整术语列表上提议带类型的边。格式不合规的提议——未知的术语名、自环边、无法识别的类型——会被自动丢弃。
没有定义的术语上的提议横幅会告诉你,该术语是未定义(去给列取别名或补一条定义)还是未落地(把它关联到一个有列的术语)。当你看到它时,该术语尚不能被智能体或目录触达。