对象上的函数
以对象和对象集为输入;只读查询函数;语义化版本;用对象集、聚合和 Ontology SQL 读取。

本课目标
读完这一课,你将能够
- 说出函数怎样接收对象和对象集,为什么对象集最省
- 说出查询函数是什么,以及它的名字和版本规则
- 用对象集、聚合和一条只读 SQL 写出「有延期风险的订单」的读取部分
把对象交给函数
对象类型建好以后,函数可以直接把它们当类型来用:参数可以是一个对象、一组对象,或者一个对象集;函数里可以按需搜索、沿关系走,也可以修改。人们常把这类函数叫作「对象上的函数」,但它并不是另一种东西,只是读了对象的函数。
对象集(最省)
什么都没加载,用到才取;只要个数或合计时,由后端直接算好。
对象数组
先把这些对象全部加载进函数,适合确实要逐个处理的场合。
单个对象(最费)
每次调用都要加载一次;只有类型里本来就只有一个对象,或业务确实逐个处理时才用。
读者会踩的坑,是在循环里一个一个去取对象:每一轮都是一次往返,最慢也最贵。正确的做法是一次取回,或者干脆让后端聚合。并行发起请求只会更快,不会更省。
还有一条权限规则:函数读对象时,用的是调用者本人的权限。两个人调用同一个函数,可能看到不同的对象,得到不同的结果。这是有意为之。
查询函数:只读,可以被调用
查询函数是函数里只读的那一部分,可以选择通过 API 暴露出去。它不能有副作用,要改数据必须用 Action。它的名字(API name)要用小写驼峰,少于 100 个字符,不以数字开头,也不能和同一个仓库导入的别的查询重名。「有延期风险的订单」写成查询函数,大致是这个形状:
// Pseudocode: illustrates inputs and outputs, not publishable source.
query atRiskOrders(orders: ObjectSet<salesOrder>, byDate: date): ObjectSet<salesOrder> {
// keep the orders whose open work orders cannot finish before byDate
}
查询函数按语义化版本发布。Automate 的 function 效果指定 version,也可以设 autoUpgrade。不要把 API 名字理解成永远执行最新打标签的版本。
函数的另一个常见用途是自定义聚合:图表按用户当下选中的对象集,即时算出一个值,例如按产线看「准时交付率」。分组和口径由界面里的选择决定,事先写不成一条固定的聚合,就交给函数。
在 AIDC 里:读的部分今天就能做
这个问题可以拆成两半:先圈出候选,再判断。圈候选是读,AIDC 今天就能做。对象集把「未完成的工单」写成一句话,聚合按订单汇总还差多少:
const client = semantic.ontology();
const open = client.objects("workOrder").where({ status: { $in: ["released", "running", "paused"] } });
const left = await open.aggregate({
$select: { "plannedQty:sum": "unordered", "goodQty:sum": "unordered" },
$groupBy: { orderNo: "exact" },
});
如果只是想在结果里多一列,例如每张订单的工单数,也不必写函数:withProperties 给对象集临时加一个沿关系计数的派生属性,读的时候算。派生属性不能用来过滤,也不能排序。
const orders = client.objects("salesOrder").withProperties({
workOrderCount: (b) => b.pivotTo("workOrders").aggregate("$count"),
});
想把订单和工单连起来一起看,可以用 Ontology SQL 的一条只读 SELECT:表名就是对象类型的 API name,一次最多 10,000 行,20 秒。把它存成文件:
SELECT o."orderNo", o."promisedDate",
sum(w."plannedQty" - w."goodQty") AS remaining
FROM "salesOrder" o
JOIN "workOrder" w ON w."orderNo" = o."orderNo"
WHERE o.status = 'inProduction' AND w.status <> 'done'
GROUP BY 1, 2
ORDER BY 2
LIMIT 50
aidc semantic sql --file at-risk.sql
剩下的是判断:余量除以产线每班产能,来不来得及在交期前干完?这是逐行计算,工作流的计算步骤能做。要不要升级处理、话怎么说,才是需要判断的事,交给智能体或 AI 分析步骤。两类活不要混在一起:数字由表达式算,结果才可复核。
要点
- 函数可以接收对象、对象数组或对象集;对象集最省,因为用到才加载,合计由后端算。
- 别在循环里一个一个取对象;一次取回,或让后端聚合。
- 查询函数只读,没有副作用。它按语义化版本发布;Automate 指定版本,并可设
autoUpgrade。 - AIDC 里读取用对象集、聚合和一条只读 SQL;判断留给工作流步骤、智能体。
练一练
把「有延期风险的订单」的读取部分做出来
用示例工厂的 salesOrder、workOrder 和 productionLine。
用 aidc semantic aggregate workOrder 按 orderNo 分组,求 plannedQty 与 goodQty 的合计;--where 只留下 released、running、paused 的工单。
把上面的 SQL 改成只看交期在 7 天内的订单,并按 promisedDate 从早到晚排序。
列出「有延期风险」这个判断里,哪些是读,哪些是逐行算,哪些需要模型判断,各交给谁。
小测
选一个答案,马上看解析。
Q1函数的入参用哪一种最省?
对象集在真正需要数据之前不加载;只要个数或合计时,由后端算好,函数拿到的只是结果。
Q2关于查询函数,哪句话对?
查询函数是只读的那一部分,可以通过 API 暴露;写数据的入口只有 Action。
Q3在 AIDC 里,把未完成的工单按订单汇总还差多少,最直接的做法是?
聚合由后端一次算完,不必为这一步再写查询函数。逐张订单取回工单,是要避开的循环加载。