属性与基础类型

第 2 课 · 共 7 课 约 8 分钟

全部基础类型的一张表;哪些能做主键和标题键;小数、日期、数组、布尔的取值与坑。

本课目标

读完这一课,你将能够

  • 说出属性带哪些元数据,写对一个属性的定义
  • 用基础类型表判断一个类型能不能做主键或标题键
  • 写出小数、日期、数组、布尔的取值,避开各自的坑

属性是什么

上一节定好了对象类型的骨架,这一节看骨架上的每一根骨头:属性。属性(Property)是对象某一方面特征的定义,相当于数据表的一列;属性值是某个对象在这一列上的取值。

除了名字和类型,一个属性还带着一组元数据,让人和智能体读得懂它:

  • name:API name,camelCase,最多 64 个字符,同一个对象类型里不能重复。
  • title 和 comment:显示名和说明,写给人看。
  • unit:单位,最多 16 个字符。数值有了单位,读的人就不用猜。
  • synonyms:同义词。智能体靠它按业务说法找到属性,比如把 goodQty 找成「良品数」。
  • visibility 和 status:让应用知道这个属性该多显眼、能不能依赖。

元数据写全的属性长这样。它的值大多来自数据源里的一列,也可以只在语义层维护,那是第 7 节的内容。

{ "name": "goodQty", "type": "integer", "title": "Good quantity", "unit": "pcs",
  "synonyms": ["yield", "good count"], "comment": "Units that passed final inspection." }

应用和 Action 按 API name 引用属性,所以改类型、删属性都是破坏性改动,要走分支和提案;只改显示名、说明和同义词,不会打断任何引用。

基础类型:一张全表

基础类型(base type)决定属性存什么形状的值,也决定应用能对它做什么。AIDC 支持 string、integer、long、short、byte、boolean、float、double、decimal、date、timestamp、array、struct、vector、geopoint、geoshape、attachment、mediaReference、timeseries、geotimeSeriesReference、cipherText、marking。最常被问的是:哪个类型能做主键,哪个能做标题键?

能做标题键吗能做主键吗
string、integer、short能能
date、timestamp能不建议,给警告
boolean、byte、long能不建议,给警告
float、double、decimal能不能
array内层类型能做时才能不能
geopoint、cipherText能不能
vector、struct、geoshape、marking不能不能
attachment、mediaReference、timeseries、geotimeSeriesReference不能不能

「不能」的,在定义时就会被拒绝;「不建议」的,能保存,但会给一个警告。

这些类型也决定了 Semantic 数据库里的列类型:string、marking、cipherText 是 text;integer、short、byte、long 是 bigint;float、double 是 double precision;decimal 是 numeric;boolean 是 boolean;date、timestamp 分别是 date、timestamptz;其余类型是 jsonb。

给一个属性选类型的四个问题

遇到一个新字段,不用背表,按顺序问四个问题:

  1. 它是名字还是数?

    编号、代码是 string,计数是 integer,金额是 decimal,测量值和评分是 double。

  2. 只有日期,还是精确到时刻?

    承诺交期只要日期,用 date;工单的开始和到期要精确到时刻,用 timestamp。

  3. 一个值,还是多个值?

    多个同类值用 array;几个有名字的字段用结构体,后面的课会讲。

  4. 它要做主键或标题键吗?

    回到上面的表查一遍,再决定。

最常见的坑是全部写成 string。ERP 导出的文本里什么都是字符串,照单全收的话,数量没法求和,日期没法比较,排序也会按字母来。类型在定义里选对一次,比在每个应用里各转换一遍划算得多。

选类型时会踩的坑

DECIMAL

金额用 decimal

金额和要精确的数量用 decimal。它和 long 读出来都是字符串,例如 "18450.00",先转成数字再相加。

DATE

日期和时刻分开

date 只有日期,写成 YYYY-MM-DD,没有时区;timestamp 是精确到时刻的 UTC ISO 8601。promisedDate 是日期,dueAt 是时刻。别拿它们做主键,存储格式和显示格式不同,容易撞。

BOOLEAN

布尔只有两种

「未检、通过、不通过」是三种状态,别用布尔加空值,用带 enum 约束的 string。布尔做主键的话,整个类型最多只有两个对象。

LONG

大整数用字符串

大于 1e15 的 long,在 JavaScript 前端里会丢精度。编号用 string,计数用 integer,long 留给真正需要的场合。

数组要同时写 arraySubType:客户的标签是 array 加 string。数组里不能有 null,不能嵌套,vector 和 timeseries 也不能放进数组。下面是 SalesOrder 的定义和读回来的一个对象,注意 totalUsd 的写法。

{
  "kind": "objectType",
  "apiName": "SalesOrder",
  "title": "Sales order",
  "schema": {
    "titleColumn": "orderNo",
    "columns": [
      { "name": "orderNo", "type": "string", "primaryKey": true, "title": "Order no." },
      { "name": "orderDate", "type": "date", "title": "Order date" },
      { "name": "promisedDate", "type": "date", "title": "Promised date" },
      { "name": "totalUsd", "type": "decimal", "title": "Order total", "unit": "USD" },
      { "name": "customerId", "type": "string", "title": "Customer", "references": { "entity": "Customer", "column": "customerId" } }
    ]
  }
}
{
  "__apiName": "SalesOrder",
  "__primaryKey": "SO-2026-0412",
  "__title": "SO-2026-0412",
  "orderNo": "SO-2026-0412",
  "orderDate": "2026-09-02",
  "promisedDate": "2026-10-15",
  "totalUsd": "18450.00",
  "customerId": "C-1008"
}

下一节讲那些不是「一个数字或一段文字」的类型:位置、时间序列、向量、附件。

要点

  • 基础类型决定值的形状;string、integer、short 能做主键,小数、数组、结构体等不能。
  • 标题键的限制比主键松:小数和地理点也行,vector、struct、时间序列等不行。
  • 金额用 decimal;date 没有时区,timestamp 是 UTC 时刻。
  • decimal 和 long 读出来是字符串;大于 1e15 的 long 在前端会丢精度。
  • 布尔只有两种状态,三种以上用带 enum 约束的 string。

练一练

给「物料」选类型

material 有 materialCode、name、unit、onHandQty、safetyStockQty、leadTimeDays 六个属性。

为六个属性各选一个基础类型,指出主键。ERP 里的库存量有时带小数(按千克计),你会怎么改?

小测

选一个答案,马上看解析。

Q1SalesOrder.totalUsd 是金额,要精确到分。选哪个类型?

Q2把 machine.vibration(timeseries)设成标题键,会怎样?

Q3为什么编号类字段通常用 string,而不用 long?

延伸阅读