ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Activepieces Tables 内置关系数据库完全指南:表、字段、记录、Webhook 与过滤语义

Activepieces Tables 内置关系数据库完全指南:表、字段、记录、Webhook 与过滤语义 Activepieces Tables 内置关系数据库完全指南表、字段、记录、Webhook 与过滤语义【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepiecesActivepieces 内置了名为Tables的关系型数据库能力无需外部数据库即可存储结构化数据带类型的列与行在类似电子表格的界面中编辑并可直接接入 Flow 作为触发器与动作的数据源。本文以 brain/knowledge/data-storage-observability/tables.md 为核心骨架结合packages/server/api、packages/core/shared、packages/pieces/core/tables等目录下的源码实现完整讲解 Tables 的实体模型、服务层设计、权限模型、Webhook 事件链路、字段重排原理以及内存过滤、日期类型、并发写入等关键 Gotchas帮助你在 CE社区版、EE企业版与 Cloud 上正确构建和运维基于 Tables 的自动化流程。Tables 是什么项目内建的关系型数据层Tables 是 Activepieces 自带的轻量关系型数据库核心定位有三点无外部依赖数据以表Table→ 字段/列Field→ 记录/行Record→ 单元格Cell四级模型存放全部作用域scoped在项目project之下不需要用户自建 PostgreSQL 或 MySQL电子表格式交互Web 端提供基于 react-data-grid 的表格编辑页支持列拖拽重排、单元格编辑等类 Excel 体验原生接入 Flow通过内置的Tables piece位于 packages/pieces/core/tables以触发器和动作的形式读写表数据也可通过内部 REST APIBearer Token 认证直接操作。从源码看三个 REST 控制器分别挂载在/v1/tables、/v1/fields、/v1/records前缀下统一由tablesModule注册见 tables.module.ts并在packages/server/api/src/app/app.ts中挂载进应用。此外模块还注册了entitiesMustBeOwnedByCurrentProject钩子确保返回给客户端的实体都属于当前项目。实体模型与层级关系实体含义关键字段来自packages/core/shared/src/lib/automation/tables/Table表name、folderId、projectId、externalId、statusENABLED/DISABLED、triggerON_NEW_RECORD/ON_UPDATE_RECORD见 table.tsField列name、externalId、type、tableId、projectId、positionSTATIC_DROPDOWN额外携带data.options见 field.tsRecord行tableId、projectIdPopulatedRecord携带按fieldName索引的 cells见 record.tsCell单元格recordId、fieldId、projectId、value存储为 VARCHAR见 cell.tsTableWebhook表事件 → Flow 的桥tableId、events、flowId、projectId见 table-webhook.tsFieldType五种字段类型FieldType枚举定义在 field.tsexport enum FieldType { TEXT TEXT, NUMBER NUMBER, DATE DATE, DATETIME DATETIME, STATIC_DROPDOWN STATIC_DROPDOWN, }其中TEXT/NUMBER/DATE/DATETIME属于普通分支STATIC_DROPDOWN是唯一携带结构化data.options的类型选项为{ value: string }数组。共享层用z.union([...])对两种分支做 Zod 校验——这个 union 分支的维护问题详见下文扩展 FieldType一节。字段数量上限由环境变量AP_MAX_FIELDS_PER_TABLE控制默认100在field.service.ts的validateCount({ projectId, tableId, insertCount })中强制校验见 field.service.tsasync validateCount({ projectId, tableId, insertCount 1 }: ValidateCountParams): Promisevoid { const countRes await this.count({ projectId, tableId }) if (countRes insertCount system.getNumberOrThrow(AppSystemProp.MAX_FIELDS_PER_TABLE)) { throw new ActivepiecesError({ code: ErrorCode.VALIDATION, params: { message: Max fields per table reached: ... }, }) } }position列的规范排序字段文档强调position是规范术语避免使用 order / displayOrder / index 等叫法表示表内列从 0 开始的顺序字段查询一律按position ASC, created ASC排序见fieldService.getAlltable.exportTable()导出时遵循同样的顺序新建字段默认取MAX(position) 1追加到末尾fieldService.create中position: request.position ?? (maxPosition ?? -1) 1而模板/导入路径直接传源数组下标保证顺序不依赖插入时序。工作原理从记录事件到 Flow 触发Webhook 事件链路每次记录创建/更新/删除后record-side-effects.ts中的recordSideEffects.handleRecordsEvent()会根据tableId 事件类型找出匹配的TableWebhook支持RECORD_CREATED、RECORD_UPDATED、RECORD_DELETED三种事件见 table-webhook.ts将记录作为 payload 触发关联的 Flow。该调用点位于 record.controller.ts创建、更新、删除三个 POST 路由在操作完成后都会调用recordSideEffects(fastify.log).handleRecordsEvent({...})。服务端实体TableWebhookEntity与共享 schema 一一对应见 table-webhook.entity.ts。Tables pieceFlow 侧的读写接口packages/pieces/core/tables 提供了完整的一套触发器与动作触发器Triggersnew-record.tsNew Record、updated-record.tsUpdated Record、deleted-record.tsDeleted Record动作Actionscreate-table、create-records、get-record、find-records、update-record、delete-record、clear-table、delete-table、download-table。所有动作通过httpClient.sendRequest调用内部 API认证方式为AuthenticationType.BEARER_TOKENtoken 取自context.server.token见 find-records.ts。以 Find Records 为例它支持 9 种过滤操作符并在发送请求前按字段类型做客户端校验propsValidation.validateZodNUMBER字段拒绝非数字、DATE/DATETIME字段拒绝无法解析的日期字符串其余类型按字符串处理——这与下文服务端内存过滤的语义相互印证。RBAC 权限模型表/字段/记录路由通过securityAccess.project(...)校验READ_TABLE/WRITE_TABLE权限见 record.controller.tsVIEWER角色只读ENGINE / SERVICE两类 principal 跳过角色检查这也是 Tables piece 与 MCP/agent 路径能直接读写的原因。列重排一条 SQL 完成的原子重排POST /v1/fields/reorder是值得单独讲解的接口请求体定义在 fields.dto.tsexport const ReorderFieldsRequest z.object({ tableId: z.string(), fieldIds: z.array(z.string()), })客户端提交的是它已经持有的完整有序 id 列表服务端在 field.service.ts 中通过一条UPDATE ... FROM unnest(fieldIds) WITH ORDINALITY将 position 一次性重排为0..n-1UPDATE field AS f SET position ordering.ord - 1 FROM unnest($1::text[]) WITH ORDINALITY AS ordering(id, ord) WHERE f.id ordering.id AND f.projectId $2 AND f.tableId $3 AND f.position IS DISTINCT FROM ordering.ord - 1两点设计值得注意幂等且安全WHERE 条件限定projectId tableId所以传入外表的 id 或过期 id 是 no-op不会影响其他表UI 联动Web 端编辑页基于 react-data-grid列拖拽draggablecolumns onColumnsReorder直接生成这份有序 id 列表。Gotchas必须知道的实现细节与坑文档与源码揭示了若干容易踩坑的语义逐一说明。1. 过滤是内存级的且缺失单元格视为空串EQ / NEQ / GT / CO / EXISTS / NOT_EXISTS等过滤操作符全部在内存中求值doesCellValueMatchFilters不是 SQL 条件下推。由于缺失的 cell 被当作空字符串处理NEQ不等于和NOT_EXISTS不存在都会匹配未设置的列——如果你期望该列存在且有值务必使用EXISTS而不是NEQ空串。2. DATE 与 DATETIME 存的是同一个值DATE和DATETIME单元格在存储层面完全等价——都是toISOString()产生的 ISO-8601 UTC 时间点。二者的差异只体现在Web 编辑器DATETIME在Calendar之外额外提供TimePicker展示格式。更关键的是写入时没有任何按类型的值强制转换coercion因此一个 DATE 列可以合法地存任意文本。这意味着数据质量完全由写入方piece 动作 / API 调用方保证。3. 只有 GT/GTE/LT/LTE 是日期感知的只有GT/GTE/LT/LTE四个操作符能感知日期类型——原因是doesCellValueMatchFilters被传入了字段类型其余操作符一律按原始字符串比较。后果是对日期列做EQ…T14:30:00Z与…T14:30:00.000Z这两种同一时刻的不同拼写匹配不上当求值器无法解析字段类型时过滤会回退到parseFloat。4. 扩展 FieldType 需要同时改三处 union 一处 switch新增一个FieldType成员时文档明确指出必须同步修改field.ts 中的枚举fields.dto.ts 中非 dropdown 的z.union([...])分支——漏改会导致POST /v1/fields直接拒绝该类型packages/core/piece-types/.../tables.ts中的对应 unionfield.service.createFromState增加一个case——该方法的default:会抛出Unsupported field type而所有模板、project-release、MCP table-create 路径都会路由经过它见 field.service.ts。好消息是无需数据库迁移field.type是普通 varchar没有 Postgres enum 或 CHECK 约束。5. 批量写入上限 50 条/批record.create()的批量插入每批最多50 条且是事务性的——单批内任一失败则整批回滚。超过 50 条的写入需要调用方自行分批。6. permission 参数必须显式传入新增任何 table/field/record 路由时securityAccess.project(...)的permission参数是必填的——传undefined会静默放行任意项目成员形成越权漏洞。7. validateCount 在批量路径上存在竞态单次创建时的field.validateCount()检查在批量路径上会竞态所有并发创建读到的是同一个保存前的 count都会通过检查。因此批量/导入路径table.create携带 fields、project-state/project-replace apply必须在Promise.all之前用批量大小一次性调用validateCount({ insertCount })。8. 并发重排是 last-write-wins并发的字段重排与字段重命名一样是最后一次写入生效没有分布式锁。此外通过 project-release apply 重排已有字段不被支持FieldState不携带 position数组顺序只作用于新建字段。9. Web 客户端缓存 fieldIndexWeb 客户端存储的是位置性的cell.fieldIndex引用因此字段移动后必须重映射每条记录的 cells——这也是列拖拽重排后 UI 能正确刷新而不会错位的实现约束。关键文件导航按文档给出的 Key files 整理如下便于深入源码模块与路由tables.module.ts — 模块注册与三个路由前缀/v1/tables、/v1/fields、/v1/records表服务table/ —table.service.tsCRUD、导出、webhook 管理、table.controller.ts、TableEntity/TableWebhookEntity字段服务field/ —field.service.ts含createFromState、validateCount、reorder、field.controller.ts、FieldEntity记录服务record/ —record.service.tsCRUD、批量操作、record.controller.ts、RecordEntity/CellEntity、record-side-effects.ts触发 TableWebhook Flow共享 schema 与 DTOtables/ — Table/Field/Record/Cell/TableWebhook 模型以及dto/fields.dto.ts、dto/records.dto.ts、dto/tables.dto.ts中的请求/响应校验Web 编辑页tables/id/index.tsx — 基于 react-data-grid 的表格编辑页面前端特性模块features/tables — 编辑器组件、React Query hooks、客户端/服务端状态 store、API 调用Tables piecepackages/pieces/core/tables — Flow 侧触发器与动作覆盖新/更新/删除记录触发与建表、增删改查、清空等动作。小结何时使用 TablesTables 适合作为 Activepieces 工作流内部的结构化状态库数据与 Flow 同处一个平台无需运维外部数据库电子表格 UI 降低维护成本Webhook 事件天然驱动自动化。但它的过滤是内存级的、日期类型不做写入强校验、并发批量写入有竞态边界因此在高并发写入、复杂 SQL 聚合、强类型约束场景下仍应评估是否将数据迁移到外部关系型数据库再通过既有数据库类 piece 接入。【免费下载链接】activepiecesAI Agents MCPs AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表