Semantic · 旧的数据层(原数据 SDK)
1.20.0 起数据 SDK 并进 Semantic:读对象用
semantic.ontology().objects(…)(对象集、聚合、链接),实时用objectSet.subscribe(…),改数据只走 Action;数据从数据源进来(Object Type 定义里的datasources,见数据流与数据源)。本页的data.*与aidc data照样能用;直接写对象(create / update / delete)只给开发者,新代码请用 Action。
公司的数据层:语义层对象存在 AIDC 中枢(Supabase Postgres,按公司隔离),这里是它的增删改查、批量导入、聚合、实时订阅,以及把 ERP / MES 的数据同步进来(sync)。另一半是数据分析的常用小工具(解析、画像、聚合、呈现)。
import { data } from "/developer/sdk/v1/aidc.js";
数据层
应用和智能体不直连 ERP:发布端只读地把数据源的变化推上来,按 Object Type 定义里的数据源(datasources)写进对象的「数据源层」;人和智能体的修改写进「语义层改动」;查询读两者合并后的当前值。数据源永远只读、永远不会被改。
ERP / MES ──发布端(只读)──▶ 数据流 ──同步绑定──▶ 对象.source ─┐
├─▶ 对象.props(当前值)──▶ 应用 · 智能体
Action(成员)/ 数据 SDK(开发者)──▶ 对象.edits ─┘ 改动永远不回写 ERP
查询与读取
const lines = data.table("production.order_line");
const page = await lines.list({ where: { line_code: "L01-05" }, sort: ["-ok"], limit: 50 });
// page.objects[i].props:当前值;page.total;page.seq(从它订阅,中间的变化不会丢)
const all = await lines.all({ where: { day: "2026-09-26" } }); // 翻页取全(每页 500)
const { object, linked, history } = await lines.get("100000012345|L01-05", { link: "production.order_line.line_code", history: true });
const byLine = await lines.aggregate({ groupBy: ["line_code"], metrics: { ok: ["ok", "sum"], n: "count" } });
条件同语义 SDK:{ 属性: 值 } 相等,{ gt, gte, lt, lte, ne, in, nin, contains, startsWith, null },$or: […]。includeGone: true 连数据源里已经没有的对象也要。
实时:live() 与 watch()
const view = data.table("production.order_line").live({
sort: "-ok",
onUpdate(objects, change) { render(objects); }, // 先全量,之后每次变化回调一次最新全集
onStatus({ connection }) { badge(connection); }, // connecting / live / reconnecting / paused / closed
});
view.close();
// 更底层:只要变化
// 页面隐藏超过 1 分钟,连接自动断开(paused),切回来带着序号续上、不丢不重——挂着的连接按时长计入应用的计算分钟
const sub = data.watch({ types: ["production.order_line"], after: page.seq }, {
onChange(c) { /* { seq, type, pk, op: "upsert"|"delete", props, origin: "sync"|"action"|"edit"|"import", at } */ },
onReset(seq) { /* 落后太多:重新查询 */ },
});
一条订阅服务一个页面:服务端从变化账里按序号推送(Redis 只传唤醒),断线带序号续传;应用只收到它看得见、且订阅了的类型。
写(开发者)
成员改数据请用 Action(校验、权限、留痕)。数据 SDK 的直接写只给开发者 Key 或应用里的 developer 访客(清单 semantic.write 登记了该类型):
await lines.create({ order_no: "X1", line_code: "L01-05", note: "临时插单" });
await lines.update("X1|L01-05", { issue: "缺料" }, { ifRev: 3 }); // 写进语义层改动
await lines.update("X1|L01-05", {}, { revert: ["ok"] }); // 撤销改动,回到数据源的值
await lines.remove("X1|L01-05"); // 语义层墓碑,数据源不受影响
await lines.import(rowsFromExcel, { layer: "source", mode: "mirror" }); // 批量导入:当作数据源数据;mirror = 这批就是全部
每一次写都进操作记录(谁、何时、改了什么、改前改后),并唤醒订阅端。
从数据流同步(ERP → 数据层)
await data.sync.bind({
stream: "production-progress", // 数据流(发布端装在客户箱上,只读 SAP)
type: "production.order_line",
properties: { order_no: "order", line_code: "line", plan: "plan", ok: "ok", day: "day" }, // 属性 ← 流字段
mode: "mirror", // 流的全量就是全部对象;多行汇成一个对象用 "upsert"
});
await data.sync.list(); // 每条绑定:状态、已同步到的流序号、落后几批
- 绑定建好立即全量同步一次,之后流每落账一批就在同一次发布里同步(净变化:新增 / 变化的行写 source,删掉的行标记源头已消失)。
- 类型的主键属性必须都映射上;只在语义层维护的属性(
writeback)不能从数据源同步。 - 同步失败只记在绑定上(
status: error+ 原因),不影响数据流本身;下一批到来时发现序号接不上会自动全量重同步,也可以手动data.sync.resync(id)。
aidc data bind production-progress production.order_line --map order_no=order,line_code=line,plan=plan,ok=ok,day=day
aidc data bindings
aidc data query production.order_line --where '{"status":"异常"}' --sort -gap
aidc data watch --types production.order_line
aidc data import production.order_line 导出.csv --layer source --mode mirror
分析小工具
纯函数、零依赖,浏览器与 Node 通用——解析、画像、分组聚合、透视、时间序列、异常、格式化、Markdown 表格与轻量图表,减少每个应用各写一遍的样板代码。
解析与导出
const rows = data.parseCsv(text); // RFC 4180:引号、转义、字段内换行;数字列自动转 number
const csv = data.toCsv(rows, ["月份", "营收"]);
ui.download("营收.csv", csv); // 存成文件(界面 SDK):自动加 UTF-8 BOM,Excel 直接打开中文不乱码
给 Excel 用的导出就是 CSV + ui.download,不用另找 xlsx 库。读 xlsx 请先另存为 CSV(或在服务端处理)——浏览器 SDK 不打包 xlsx 解析器。
画像
data.profile(rows);
// → [{ name, type: "number"|"date"|"string"|"boolean"|"empty", count, missing, distinct, min, max, mean, sum, top }]
聚合
data.groupBy(rows, "region", { revenue: ["amount", "sum"], orders: "count", avg: ["amount", "avg"] });
data.pivot(rows, "region", "month", "amount", "sum"); // → { columns, rows }
data.timeSeries(rows, "order_date", "month", { revenue: ["amount", "sum"] });
data.topN(rows, "revenue", 10);
data.timeBucket("2026-09-25", "week"); // → "2026-09-22"(周一)
聚合函数:sum、avg、count、min、max、distinct。
变化与异常
data.pctChange(1200, 1000); // 0.2
data.share(300, 1200); // 0.25
data.zScores([10, 12, 30]);
data.anomalies(monthly, "revenue", 2); // |z| ≥ 2 的月份
呈现
data.formatNumber(129363024); // "1.3 亿"
data.formatNumber(52300); // "5.2 万"
data.formatPercent(0.2559); // "25.6%"
data.markdownTable(rows, [["month", "月份"], ["revenue", "营收"]]);
el.innerHTML = data.barChartSvg(points, { color: "#ff4d00", format: data.formatNumber });
el.innerHTML = data.lineChartSvg(points); // 缺省按数据上下界缩放;zero: true 从 0 起
复杂图表请用 Chart.js(从 cdn.jsdelivr.net 加载,并在清单的 cdn 里声明)。
命令行
aidc data profile orders.csv
aidc data group orders.csv --by region --sum amount --count
和数据集报告一起用
企业数据集的固定报告由数据集取回(只含聚合),再用数据 SDK 做二次加工与呈现——样板「ERP 数据自动分析」就是这样做的。
本页由 developer/docs/data.md 生成 · Markdown 原文 · llms.txt