P2 Foundry
YAML 导入导出:本体即代码
对象定义不只是平台里的表单,也可以是一份可进 Git、可评审、可跨环境迁移的 YAML。导出单对象、批量导入多对象 + 链接、测试迁生产,让"本体即代码"落地。看完这 3 个故事,你就能自己把本体当代码管起来。
数据工程师
平台管理员
YAML
本体即代码
批量导入
跨环境迁移
共 3 个故事
能 / 不能速览
✅ 这个主题能做
- GET /ontology/objects/:id/export?format=yaml 导出单对象完整定义(属性 / 链接 / 动作)
- POST /ontology/objects/import 批量导入,两遍扫描:先校验、再建对象,链接可前向引用、延迟补建
- YAML 里一律用稳定 api_name(name)引用,不依赖内部自增 id,跨环境安全
- 导入返回 {total, created, skipped, errors},单个对象失败不整体回滚
- 配合 Git 做版本管理、code review,"本体即代码"
⛔ 这个主题做不了
- 导入必须带 apiVersion: zy-foundry/ontology/v1,否则整体终止
- YAML 不携带平台内部 id 与版本号,导入即新建(version 从 1 起);活跃同名对象会 Skipped 不覆盖,但已删除(deprecated)的同名对象可同名导入复活(整体替换、status 回 merged,导入结果带 revived / revived_names)
- dataSourceId 字段是环境相关的,跨环境导入后需人工核对指向
- 导出是"单对象"粒度,批量导出需自行拼多对象文档
适用角色
本主题面向两个角色:
- 数据工程师:导出 YAML 进 Git、构造批量导入文档、跨环境迁移——是核心使用者。
- 平台管理员 / 评审人:在 PR 里 review 对象定义变更,把控生产导入节奏。
业务分析师不直接接触 YAML,但消费的是"通过 YAML 导入后"的对象与指标。
能力速览(能做什么)
单对象导出
GET /ontology/objects/:id/export?format=yaml 输出标准文档(apiVersion + objectTypes),含属性(isCalculated/formula/isPII/hidden/sharedProperty)、链接(含 N:M 的 joinDataset)、动作(requiresApproval/validationRules)、implementsInterfaces 完整声明。
批量导入
POST /ontology/objects/import 两遍扫描:第一遍校验对象与文档内跨对象引用,第二遍逐个创建并补建延迟链接。
稳定标识引用
对象 / 链接 / 动作一律用 api_name(name)引用,共享属性按 api_name 解析(sharedProperty 引用自动复制默认值),不依赖内部自增 id,导出 → 导入即"复制",跨环境安全。
结果统计
导入返回 {total, created, skipped, errors},前端展示总数 / 已创建 / 跳过 / 错误四格,错误逐条可看。
版本化协同
YAML 进 Git 仓库走 PR 评审,配合对象 version 字段做"本体即代码"治理。
调整指南(怎么调整)
- 导出调整:单个对象用导出接口;要整份文档在编辑器里拼多个 objectTypes 元素。
- 导入调整:文档级错误(非法 YAML / apiVersion 不匹配 / 对象名重复)会整体终止;对象级错误记 Skipped,其余继续导入。
- 链接调整:sourceObject / targetObject 用文档内对象 name 引用,前向引用会自动延迟到全部对象建完后补建。
- 跨环境调整:导入前先查目标环境同名对象,避免 skipped;核对 dataSourceId 指向目标环境的真实数据源。
- 版本调整:YAML 不携带版本号,导入即新建对象(version 从 1 起),用 Git tag 配合记录本体重定义版本。
做得好的场景
本体即代码让对象定义享受代码级治理,特别适合以下场景:
- 版本管理与评审:对象定义进 Git,diff 一看就懂改动,PR 评审后再上生产。
- 批量交付:一套含多对象 + 链接的 YAML 一次性导入,比在界面逐个建快得多。
- 跨环境迁移:测试环境导出 → 生产导入,api_name 引用让"复制"跨环境安全。
- 审计留痕:导入结果(created / skipped / errors)可查,谁导入了什么有记录。
限制与不足
以下是明确的边界,使用前先知道:
- apiVersion 强制:导入文档必须带 apiVersion: zy-foundry/ontology/v1,不匹配整体终止。
- 导入即新建:YAML 不携带平台内部 id 与版本号;活跃同名对象导入会 Skipped(不覆盖、不更新),同名对象已删除(deprecated)时则按导入定义整体替换并复活(status 回 merged、产生新 merged 版本、结果带 revived)。
- dataSourceId 环境相关:YAML 里 dataSourceId 指向各环境自己的数据源,跨环境导入后要人工核对。
- 导出单对象粒度:导出接口一次导一个对象,整份多对象文档需自行拼接。
- 重名演示对象:演示环境已 seed customer / order / product,重复导入活跃同名会 Skipped,需改名或先删除(同名已删除的会复活,不 Skipped)。
场景故事
故事 1
把 customer 对象导出 YAML 进 Git,实现"本体即代码"
场景:本体即代码
角色:数据工程师
耗时:约 6 分钟
- 背景
- 公司定了规矩:本体定义要纳入版本管理,别只在平台上点鼠标。张工把 customer 对象导出成 YAML,提交进 Git 仓库,走 code review,实现"本体即代码"——对象定义和业务代码一样可 diff、可评审、可回滚。
- 传统做法对比
- 以前对象在平台里改完就完了,改了什么、为什么改,没有记录;别人想复用这个对象定义,只能登平台去看。现在 YAML 一份进 Git,diff 一看就懂,评审留痕,出事还能回滚。
- 角色
- 数据工程师(导出 + 提交 Git);评审人在 PR 里 review 定义变更。
- 操作步骤
-
- 打开侧边栏"YAML 导入导出",选择对象类型 customer
- 点"导出 YAML",textarea 显示完整定义
- 复制 YAML 到仓库文件 ontology/customer.yaml
- git add、commit、开 PR,邀请评审人 review 对象定义变更
- 系统响应
- 导出返回原始 YAML 文本(非 {code:0} 包装),示例:
apiVersion: zy-foundry/ontology/v1
objectTypes:
- name: customer
displayName: 客户
description: 客户基本信息
category: sales
dataSourceId: 1
baseTable: customers
pkColumn: customer_id
properties:
- name: customer_id
displayName: 客户ID
dataType: number
mappedColumn: customer_id
isPrimaryKey: true
ordinal: 1
- name: name
displayName: 客户名称
dataType: text
mappedColumn: name
ordinal: 2
- name: region
displayName: 地区
dataType: text
mappedColumn: region
ordinal: 3
- 结果洞察
- 对象定义从"平台里的一个表单"变成"Git 里一份可 diff、可评审、可回滚的资产"。接口用稳定标识(api_name)引用、不依赖内部自增 id,所以这份 YAML 跨环境、跨系统都安全。同事 review 时看 YAML 就懂对象结构,不用登平台。
- 调整建议
- 把 YAML 按对象分文件、放统一目录(如 ontology/),配 CI 校验 YAML 合法性;同义词、PII 标记、枚举约束都在 YAML 里可见,评审时重点看;别手改 YAML 再导回平台,以平台定义为准、以 YAML 为"副本 + 版本记录"。
- 动手试一试
- 登录:admin / admin1。页面路径:YAML 导入导出。输入内容:选择对象 customer → 导出 YAML。预期结果:textarea 出现 apiVersion 为 zy-foundry/ontology/v1、含 name / displayName / baseTable / pkColumn / properties 的完整 YAML。
- 限制提示
- 导出是"单对象"粒度(文档里一个 objectTypes 元素),整份多对象文档需自行拼接;导入时必须带 apiVersion: zy-foundry/ontology/v1,否则报"不支持的 apiVersion";demo 每次启动重建的是数据表,对象定义存在平台库、不会被清掉。
故事 2
从 YAML 批量导入多个对象 + 链接,两遍扫描一次搞定
场景:批量导入
角色:数据工程师
耗时:约 8 分钟
- 背景
- 另一支团队交付了一组本体 YAML(customer + order + product 三个对象,含 customer_to_order、order_to_product 两条链接),要一次性导入平台。张工把 YAML 粘贴进"YAML 导入导出"页,体验平台的"两遍扫描"导入。
- 传统做法对比
- 以前三个对象 + 两条链接要在界面逐个建:对象、属性、链接一个个点,少则一小时,多了漏配关系。现在一份 YAML 一次导入,created / skipped / errors 一次看清,比手点快一个量级。
- 角色
- 数据工程师(构造 / 粘贴 YAML 并导入)。
- 操作步骤
-
- 打开"YAML 导入导出",把含 3 个对象 + 2 条链接的 YAML 粘贴进编辑器(或直接 POST /ontology/objects/import,Content-Type: application/yaml)
- 确认 apiVersion=zy-foundry/ontology/v1,objectTypes 含 customer / order / product
- 确认链接的 sourceObject / targetObject 都用文档内对象 name 引用
- 点"导入 YAML",查看结果统计
- 系统响应
- 返回示例:
{
"total": 3,
"created": 3,
"skipped": 0,
"errors": []
}
前端展示总数 / 已创建 / 跳过 / 错误四个统计,错误为空。
- 结果洞察
- 两遍扫描的妙处在"链接可以前向引用":第一遍校验所有对象与文档内跨对象引用(比如链接 targetObject 指向文档内对象),第二遍逐个创建对象,目标对象尚未创建的前向链接延迟到全部对象建完后补建。3 个对象 + 2 条链接一次导入成功,比逐个在界面点快得多。
- 调整建议
- 链接的 sourceObject / targetObject 用对象 name(稳定标识)而非内部 id;文档内对象名不能重复,重复者按 Skipped 记错;单个对象失败不整体回滚(其余继续导),错误列表逐条可看。
- 动手试一试
- 登录:admin / admin1。页面路径:YAML 导入导出。输入内容:构造含 customer / order / product 三对象 + customer_to_order、order_to_product 两条链接的 YAML(注意演示环境已有同名 seed 对象,请用新名字如 customer_v2)。预期结果:total=3、created=3、skipped=0、errors=[];对象列表出现新对象。
- 限制提示
- 文档级错误(非法 YAML、apiVersion 不匹配、对象名在文档内重复)会整体终止导入;活跃同名对象导入会 Skipped(duplicate)不覆盖,同名对象已删除(deprecated)则按导入定义整体替换并复活;演示环境已 seed customer / order / product,重复导入活跃同名会 Skipped,需换名字或先删除。
故事 3
跨环境迁移:测试导出 → 生产导入,配合版本号管理
场景:跨环境迁移
角色:数据工程师 + 平台管理员
耗时:约 10 分钟
- 背景
- 本体 v1.2 在测试环境打磨好了,要迁到生产。张工走"测试导出 → 生产导入"的标准流程,配合 Git tag 打版本号,交付一份可追溯的迁移记录——这就是"本体即代码"的发布流程。
- 传统做法对比
- 以前环境间搬数据模型靠"对着屏幕重配一遍",漏字段、漏链接是家常便饭,环境差异还得靠人来记。现在 YAML 导出 → 导入即"复制",api_name 稳定引用让跨环境安全,Git tag 记录版本,迁移有据可查。
- 角色
- 数据工程师(导出 / 导入 / 打 tag)+ 平台管理员(把控生产导入时机)。
- 操作步骤
-
- 在测试环境"YAML 导入导出"页逐个导出 customer / order / product
- 把三份合并成一份含 3 个 objectTypes 的 YAML(apiVersion 保持 zy-foundry/ontology/v1)
- 登录生产环境,粘贴并导入(导入前先查同名对象,避免 skipped)
- 核对 dataSourceId 指向生产环境真实数据源
- 在 Git 里给本体目录打 tag(如 ontology-v1.2),写发布说明
- 系统响应
- 生产导入返回
{"total":3,"created":3,"skipped":0,"errors":[]};对象列表出现 customer / order / product,各对象 version 从 1 开始。
- 结果洞察
- 因为 YAML 里全部用 api_name 稳定标识引用(链接、动作都用 name),跨环境迁移不依赖任何内部自增 id,导出 → 导入即完成"复制"。配合 Git tag 与发布说明,生产环境的对象定义有据可查;升级前 diff 一份 YAML 就能评审影响,发布会话里再也不用"凭记忆同步"。
- 调整建议
- 迁移前先在生产查同名对象(GET /ontology/objects),避免导入 skipped;dataSourceId 是环境相关的,跨环境导入后核对 base_table 指向正确;大版本变更先在测试环境回归指标 / 查询,再上生产。
- 动手试一试
- 登录:admin / admin1。页面路径:YAML 导入导出。输入内容:把 customer 的 YAML 导出后改名(如 customer_mig),再导入。预期结果:created=1,对象列表出现 customer_mig;若直接用原名(customer 仍活跃)会 skipped(提示重名)——只有同名对象已删除时才会按导入定义复活。
- 限制提示
- YAML 不携带平台内部 id 与版本号,导入即新建对象(version 重新从 1 起);dataSourceId 字段跨环境需人工核对;若导入对象被现有指标 / 链接引用,删除或重命名需先清理依赖。
常见问题
YAML 导出的是什么?和界面上看到的一样吗?
导出的是对象的完整声明:apiVersion + objectTypes,含对象基本信息(name / displayName / baseTable / pkColumn)、属性(dataType / mappedColumn / enumValues / isPrimaryKey / isPII 等)、链接(sourceObject / targetObject / cardinality)与动作。与平台里对象定义一一对应,且全部用 api_name 稳定标识引用。
导入和"在界面新建对象"有什么区别?
导入是声明式批处理:一份 YAML 可含多个对象 + 链接,走"两遍扫描"校验与创建;对象级失败只记 Skipped 不影响其余。界面新建是单对象逐步操作,适合临时调整。两者创建的对象在系统里完全等价。
为什么导入同名对象会 skipped?
对象名(api_name)有唯一索引,已存在【活跃】同名对象时导入会报 duplicate 并按 Skipped 记录,不覆盖、不更新(想更新请在平台里编辑)。但同名对象已删除(deprecated)时不 Skipped:会按导入定义整体替换并复活——status 回 merged、产生新 merged 版本,导入结果以 revived / revived_names 呈现。
跨环境迁移安全吗?内部 id 会不会对不上?
安全。YAML 里所有引用都用 api_name(稳定标识)而不是内部自增 id,导出 → 导入不依赖任何内部 id,所以跨环境是"纯复制"。唯一要注意的是 dataSourceId 这类环境相关字段,跨环境后需人工核对。
YAML 里能带版本号吗?
不能。YAML 不携带平台内部 id 与版本号,导入即新建对象(version 从 1 起)。想记录"本体重定义版本",用 Git tag + 发布说明在仓库侧管理,与平台对象的 version 配合使用。
主题小结
一句话:YAML 导入导出让"本体即代码"落地——单对象导出进 Git、多对象批量导入(两遍扫描、链接可前向引用)、测试迁生产全走稳定 api_name。记住几个边界:必须带 apiVersion、导入即新建(活跃同名 skipped,已删除同名对象可同名导入复活)、dataSourceId 跨环境需核对、导出是单对象粒度。