对象类型:一类业务对象
对象类型、对象、对象集;主键和标题键的规则;API name、显示名、状态、可见性;写出第一份定义。

本课目标
读完这一课,你将能够
- 分清对象类型、对象和对象集,并对应到数据表
- 为一类业务对象选出主键和标题键
- 写出一份 objectType 定义,说出 API name、显示名、状态和可见性各管什么
对象类型、对象、对象集
上一门课把示例工厂的 13 个对象类型画在了同一张图上。这一节先挑「工单」,把它写成一份能提交的定义。
对象类型(Object Type)是对一类真实事物或事件的定义,比如工单。一张具体的工单是一个对象,「所有正在运行的工单」是一个对象集。它们和你熟悉的数据表一一对应:
| 数据表里 | 本体(Ontology)里 | |
|---|---|---|
| 整张表的结构 | 工单表的表头和列定义 | 对象类型 WorkOrder |
| 一行 | 表里的一行数据 | 一个对象,比如工单 WO-20260901-017 |
| 筛出来的几行 | 「状态 = 运行中」的若干行 | 一个对象集 |
| 一列 | goodQty 这一列 | 一个属性 |
对象大多来自数据源里的行,也可以完全由 Action 的 createObject 规则新建。数据源接入只读。普通 Action 规则只改语义层。配置 writeback webhook 的 Action 还能修改外部系统。
两把钥匙:主键和标题键
每个对象类型都要指定两个属性。主键让每个对象唯一,标题键是给人看的名字。WorkOrder 用 workOrderNo 做主键;Customer 的主键是 customerId,标题键是 name,因为人认的是公司名,不是编号。
- 每个对象类型都必须有主键;新建的类型只写一个主键属性。存量复合主键原样保留时给警告。新建类型或修改主键时,平台拒收复合主键。
- 主键值不能重复,也不能变。编辑和关系都挂在主键值上,主键一变,人改过的值和已有的关系就对不上了。
- 改主键属于破坏性改动,要走分支和提案,不能悄悄改。
- 标题键只管显示,不要求唯一;不写就用主键。
用 ERP 导出文件里的行号当工单主键。下一次导出,行号变了,人在工单上做的标记全部对不上。
用 ERP 里本来就有的工单号 workOrderNo:唯一、稳定,业务人员也认识。
有了主键,取回一个对象只要「类型 + 主键」。读回的每个对象都带着 __primaryKey、__apiName 和 __title,最后一个就是标题键的值。
const client = semantic.ontology();
const order = await client.objects("WorkOrder").fetchOne("WO-20260901-017");
// order.__primaryKey, order.__apiName === "WorkOrder", order.__title
名字与元数据
对象类型有两套名字:写给代码的,和写给人的。
给代码用的名字
Object Type 用 PascalCase,例如 WorkOrder;属性用 camelCase,例如 goodQty。Object Type 的 API name 最多 100 个字符。Postgres 视图名称另限 63 字节。Action、SQL 的表名和应用都在引用它,起好就不要改。
给人看的名字
显示名 title、复数显示名 pluralDisplayName、说明,还有同义词 synonyms:智能体和搜索按业务说法找到它。
状态
active、experimental、deprecated、example:告诉别的建模者和应用,这一类现在能不能依赖。约定是:active 的类型不能直接删除或改 API name,example 只用于演示,不进正式流程。
可见性与类型组
visibility 取 NORMAL、PROMINENT、HIDDEN:重要的先显示,隐藏的不显示。groups 给类型打标签,类型多了好筛选。
同义词值得认真写。业务里有人说「生产单」,有人说「作业单」,把它们都写成 WorkOrder 的同义词,智能体按哪种说法问都能找到。每个类型最多写 12 个,每个不超过 40 个字符。
下面是 WorkOrder 的一份最小定义(省略了 sku、orderNo 两个外键)。columns 里每一项是一个属性,titleColumn 指定标题键,references 是外键,下一门课会把它变成关系。外键指向的类型(这里是 ProductionLine)要么已经存在,要么在同一批里一起提交。
{
"kind": "objectType",
"apiName": "WorkOrder",
"title": "Work order",
"description": "One production run of one product on one line.",
"schema": {
"pluralDisplayName": "Work orders",
"visibility": "PROMINENT",
"synonyms": ["job", "production order"],
"groups": ["production"],
"titleColumn": "workOrderNo",
"columns": [
{ "name": "workOrderNo", "type": "string", "primaryKey": true, "title": "Work order no." },
{ "name": "status", "type": "string", "title": "Status" },
{ "name": "plannedQty", "type": "integer", "title": "Planned quantity", "unit": "pcs" },
{ "name": "goodQty", "type": "integer", "title": "Good quantity", "unit": "pcs" },
{ "name": "scrapQty", "type": "integer", "title": "Scrap quantity", "unit": "pcs" },
{ "name": "startAt", "type": "timestamp", "title": "Start" },
{ "name": "dueAt", "type": "timestamp", "title": "Due" },
{ "name": "lineCode", "type": "string", "title": "Line", "references": { "entity": "ProductionLine", "column": "lineCode" } }
]
}
}
提交前先只检查:--dry-run 会告诉你引用是否闭合、相对上一个语义版本有哪些破坏性改动。智能体不直接改 main,要先开分支。
# check only: do the references close? any breaking changes?
aidc semantic define ontology/ --dry-run
# an agent works on a branch instead of main
aidc semantic branch create add-work-order
aidc semantic branch modify add-work-order ontology/ --dry-run
# read the definition back
aidc semantic object-types WorkOrder
下一节讲属性:每个属性该选什么类型,哪些类型能做主键和标题键。
要点
- 对象类型是一类事物的定义,对象是其中一个,对象集是满足条件的一组。
- 主键要唯一、稳定,标题键给人看;新建类型只写一个主键属性。
- API name 给代码用,起好别改;显示名、同义词、状态、可见性给人和应用看。
- 先
--dry-run检查再提交;智能体在分支上写定义,不直接改 main。
练一练
把「设备」写成一个对象类型
示例工厂的设备 Machine 有 machineId、lineCode、model、installedOn 等属性。
为 Machine 选出主键和标题键,各写一句理由。再想一想:如果 MES 里的设备编号有时会重新编排,该怎么办?
照 WorkOrder 的写法,为 Machine 写一份 objectType JSON:至少五个属性,起好 API name、显示名和两个同义词。
在自己的 Semantic 里对这份文件跑 aidc semantic define 加 --dry-run(智能体则用分支),读一读它报告了什么。
小测
选一个答案,马上看解析。
Q1工单数据源里每行有一个自增行号,还有 ERP 的工单号 WO-20260901-017。主键该用哪个?
编辑和关系都挂在主键值上,所以主键要唯一、稳定。重新导出后,行号可能变化。把计划数量和开始时间拼成单列,仍是单属性主键,但不能保证唯一、稳定。新建复合主键会被拒收。
Q2「所有状态为运行中的工单」在 Semantic 里是什么?
对象类型定义一类,对象是其中一个,对象集是满足条件的一组。筛选只会得到一个对象集,不会产生新的类型。
Q3下面哪一个符合新建 Object Type 的 API name 命名标准?
Object Type 和 Interface 用 PascalCase,例如 WorkOrder。属性用 camelCase。存量小写类型名可继续用,新定义必须遵守标准。