查看 Markdown

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();                        // 每条绑定:状态、已同步到的流序号、落后几批
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