置關(guān)系數(shù)據(jù)庫完全指南:表、字段、記錄、Webhook 與過濾語義)
Activepieces Tables 內(nèi)置關(guān)系數(shù)據(jù)庫完全指南表、字段、記錄、Webhook 與過濾語義【免費(fèi)下載鏈接】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項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ac/activepiecesActivepieces 內(nèi)置了名為Tables的關(guān)系型數(shù)據(jù)庫能力無需外部數(shù)據(jù)庫即可存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù)帶類型的列與行在類似電子表格的界面中編輯并可直接接入 Flow 作為觸發(fā)器與動(dòng)作的數(shù)據(jù)源。本文以 brain/knowledge/data-storage-observability/tables.md 為核心骨架結(jié)合packages/server/api、packages/core/shared、packages/pieces/core/tables等目錄下的源碼實(shí)現(xiàn)完整講解 Tables 的實(shí)體模型、服務(wù)層設(shè)計(jì)、權(quán)限模型、Webhook 事件鏈路、字段重排原理以及內(nèi)存過濾、日期類型、并發(fā)寫入等關(guān)鍵 Gotchas幫助你在 CE社區(qū)版、EE企業(yè)版與 Cloud 上正確構(gòu)建和運(yùn)維基于 Tables 的自動(dòng)化流程。Tables 是什么項(xiàng)目內(nèi)建的關(guān)系型數(shù)據(jù)層Tables 是 Activepieces 自帶的輕量關(guān)系型數(shù)據(jù)庫核心定位有三點(diǎn)無外部依賴數(shù)據(jù)以表Table→ 字段/列Field→ 記錄/行Record→ 單元格Cell四級(jí)模型存放全部作用域scoped在項(xiàng)目project之下不需要用戶自建 PostgreSQL 或 MySQL電子表格式交互Web 端提供基于 react-data-grid 的表格編輯頁支持列拖拽重排、單元格編輯等類 Excel 體驗(yàn)原生接入 Flow通過內(nèi)置的Tables piece位于 packages/pieces/core/tables以觸發(fā)器和動(dòng)作的形式讀寫表數(shù)據(jù)也可通過內(nèi)部 REST APIBearer Token 認(rèn)證直接操作。從源碼看三個(gè) REST 控制器分別掛載在/v1/tables、/v1/fields、/v1/records前綴下統(tǒng)一由tablesModule注冊(cè)見 tables.module.ts并在packages/server/api/src/app/app.ts中掛載進(jìn)應(yīng)用。此外模塊還注冊(cè)了entitiesMustBeOwnedByCurrentProject鉤子確保返回給客戶端的實(shí)體都屬于當(dāng)前項(xiàng)目。實(shí)體模型與層級(jí)關(guān)系實(shí)體含義關(guān)鍵字段來自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存儲(chǔ)為 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是唯一攜帶結(jié)構(gòu)化data.options的類型選項(xiàng)為{ value: string }數(shù)組。共享層用z.union([...])對(duì)兩種分支做 Zod 校驗(yàn)——這個(gè) union 分支的維護(hù)問題詳見下文擴(kuò)展 FieldType一節(jié)。字段數(shù)量上限由環(huán)境變量AP_MAX_FIELDS_PER_TABLE控制默認(rèn)100在field.service.ts的validateCount({ projectId, tableId, insertCount })中強(qiáng)制校驗(yàn)見 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列的規(guī)范排序字段文檔強(qiáng)調(diào)position是規(guī)范術(shù)語避免使用 order / displayOrder / index 等叫法表示表內(nèi)列從 0 開始的順序字段查詢一律按position ASC, created ASC排序見fieldService.getAlltable.exportTable()導(dǎo)出時(shí)遵循同樣的順序新建字段默認(rèn)取MAX(position) 1追加到末尾fieldService.create中position: request.position ?? (maxPosition ?? -1) 1而模板/導(dǎo)入路徑直接傳源數(shù)組下標(biāo)保證順序不依賴插入時(shí)序。工作原理從記錄事件到 Flow 觸發(fā)Webhook 事件鏈路每次記錄創(chuàng)建/更新/刪除后record-side-effects.ts中的recordSideEffects.handleRecordsEvent()會(huì)根據(jù)tableId 事件類型找出匹配的TableWebhook支持RECORD_CREATED、RECORD_UPDATED、RECORD_DELETED三種事件見 table-webhook.ts將記錄作為 payload 觸發(fā)關(guān)聯(lián)的 Flow。該調(diào)用點(diǎn)位于 record.controller.ts創(chuàng)建、更新、刪除三個(gè) POST 路由在操作完成后都會(huì)調(diào)用recordSideEffects(fastify.log).handleRecordsEvent({...})。服務(wù)端實(shí)體TableWebhookEntity與共享 schema 一一對(duì)應(yīng)見 table-webhook.entity.ts。Tables pieceFlow 側(cè)的讀寫接口packages/pieces/core/tables 提供了完整的一套觸發(fā)器與動(dòng)作觸發(fā)器Triggersnew-record.tsNew Record、updated-record.tsUpdated Record、deleted-record.tsDeleted Record動(dòng)作Actionscreate-table、create-records、get-record、find-records、update-record、delete-record、clear-table、delete-table、download-table。所有動(dòng)作通過httpClient.sendRequest調(diào)用內(nèi)部 API認(rèn)證方式為AuthenticationType.BEARER_TOKENtoken 取自context.server.token見 find-records.ts。以 Find Records 為例它支持 9 種過濾操作符并在發(fā)送請(qǐng)求前按字段類型做客戶端校驗(yàn)propsValidation.validateZodNUMBER字段拒絕非數(shù)字、DATE/DATETIME字段拒絕無法解析的日期字符串其余類型按字符串處理——這與下文服務(wù)端內(nèi)存過濾的語義相互印證。RBAC 權(quán)限模型表/字段/記錄路由通過securityAccess.project(...)校驗(yàn)READ_TABLE/WRITE_TABLE權(quán)限見 record.controller.tsVIEWER角色只讀ENGINE / SERVICE兩類 principal 跳過角色檢查這也是 Tables piece 與 MCP/agent 路徑能直接讀寫的原因。列重排一條 SQL 完成的原子重排POST /v1/fields/reorder是值得單獨(dú)講解的接口請(qǐng)求體定義在 fields.dto.tsexport const ReorderFieldsRequest z.object({ tableId: z.string(), fieldIds: z.array(z.string()), })客戶端提交的是它已經(jīng)持有的完整有序 id 列表服務(wù)端在 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兩點(diǎn)設(shè)計(jì)值得注意冪等且安全WHERE 條件限定projectId tableId所以傳入外表的 id 或過期 id 是 no-op不會(huì)影響其他表UI 聯(lián)動(dòng)Web 端編輯頁基于 react-data-grid列拖拽draggablecolumns onColumnsReorder直接生成這份有序 id 列表。Gotchas必須知道的實(shí)現(xiàn)細(xì)節(jié)與坑文檔與源碼揭示了若干容易踩坑的語義逐一說明。1. 過濾是內(nèi)存級(jí)的且缺失單元格視為空串EQ / NEQ / GT / CO / EXISTS / NOT_EXISTS等過濾操作符全部在內(nèi)存中求值doesCellValueMatchFilters不是 SQL 條件下推。由于缺失的 cell 被當(dāng)作空字符串處理NEQ不等于和NOT_EXISTS不存在都會(huì)匹配未設(shè)置的列——如果你期望該列存在且有值務(wù)必使用EXISTS而不是NEQ空串。2. DATE 與 DATETIME 存的是同一個(gè)值DATE和DATETIME單元格在存儲(chǔ)層面完全等價(jià)——都是toISOString()產(chǎn)生的 ISO-8601 UTC 時(shí)間點(diǎn)。二者的差異只體現(xiàn)在Web 編輯器DATETIME在Calendar之外額外提供TimePicker展示格式。更關(guān)鍵的是寫入時(shí)沒有任何按類型的值強(qiáng)制轉(zhuǎn)換coercion因此一個(gè) DATE 列可以合法地存任意文本。這意味著數(shù)據(jù)質(zhì)量完全由寫入方piece 動(dòng)作 / API 調(diào)用方保證。3. 只有 GT/GTE/LT/LTE 是日期感知的只有GT/GTE/LT/LTE四個(gè)操作符能感知日期類型——原因是doesCellValueMatchFilters被傳入了字段類型其余操作符一律按原始字符串比較。后果是對(duì)日期列做EQ…T14:30:00Z與…T14:30:00.000Z這兩種同一時(shí)刻的不同拼寫匹配不上當(dāng)求值器無法解析字段類型時(shí)過濾會(huì)回退到parseFloat。4. 擴(kuò)展 FieldType 需要同時(shí)改三處 union 一處 switch新增一個(gè)FieldType成員時(shí)文檔明確指出必須同步修改field.ts 中的枚舉fields.dto.ts 中非 dropdown 的z.union([...])分支——漏改會(huì)導(dǎo)致POST /v1/fields直接拒絕該類型packages/core/piece-types/.../tables.ts中的對(duì)應(yīng) unionfield.service.createFromState增加一個(gè)case——該方法的default:會(huì)拋出Unsupported field type而所有模板、project-release、MCP table-create 路徑都會(huì)路由經(jīng)過它見 field.service.ts。好消息是無需數(shù)據(jù)庫遷移field.type是普通 varchar沒有 Postgres enum 或 CHECK 約束。5. 批量寫入上限 50 條/批record.create()的批量插入每批最多50 條且是事務(wù)性的——單批內(nèi)任一失敗則整批回滾。超過 50 條的寫入需要調(diào)用方自行分批。6. permission 參數(shù)必須顯式傳入新增任何 table/field/record 路由時(shí)securityAccess.project(...)的permission參數(shù)是必填的——傳undefined會(huì)靜默放行任意項(xiàng)目成員形成越權(quán)漏洞。7. validateCount 在批量路徑上存在競態(tài)單次創(chuàng)建時(shí)的field.validateCount()檢查在批量路徑上會(huì)競態(tài)所有并發(fā)創(chuàng)建讀到的是同一個(gè)保存前的 count都會(huì)通過檢查。因此批量/導(dǎo)入路徑table.create攜帶 fields、project-state/project-replace apply必須在Promise.all之前用批量大小一次性調(diào)用validateCount({ insertCount })。8. 并發(fā)重排是 last-write-wins并發(fā)的字段重排與字段重命名一樣是最后一次寫入生效沒有分布式鎖。此外通過 project-release apply 重排已有字段不被支持FieldState不攜帶 position數(shù)組順序只作用于新建字段。9. Web 客戶端緩存 fieldIndexWeb 客戶端存儲(chǔ)的是位置性的cell.fieldIndex引用因此字段移動(dòng)后必須重映射每條記錄的 cells——這也是列拖拽重排后 UI 能正確刷新而不會(huì)錯(cuò)位的實(shí)現(xiàn)約束。關(guān)鍵文件導(dǎo)航按文檔給出的 Key files 整理如下便于深入源碼模塊與路由tables.module.ts — 模塊注冊(cè)與三個(gè)路由前綴/v1/tables、/v1/fields、/v1/records表服務(wù)table/ —table.service.tsCRUD、導(dǎo)出、webhook 管理、table.controller.ts、TableEntity/TableWebhookEntity字段服務(wù)field/ —field.service.ts含createFromState、validateCount、reorder、field.controller.ts、FieldEntity記錄服務(wù)record/ —record.service.tsCRUD、批量操作、record.controller.ts、RecordEntity/CellEntity、record-side-effects.ts觸發(fā) TableWebhook Flow共享 schema 與 DTOtables/ — Table/Field/Record/Cell/TableWebhook 模型以及dto/fields.dto.ts、dto/records.dto.ts、dto/tables.dto.ts中的請(qǐng)求/響應(yīng)校驗(yàn)Web 編輯頁tables/id/index.tsx — 基于 react-data-grid 的表格編輯頁面前端特性模塊features/tables — 編輯器組件、React Query hooks、客戶端/服務(wù)端狀態(tài) store、API 調(diào)用Tables piecepackages/pieces/core/tables — Flow 側(cè)觸發(fā)器與動(dòng)作覆蓋新/更新/刪除記錄觸發(fā)與建表、增刪改查、清空等動(dòng)作。小結(jié)何時(shí)使用 TablesTables 適合作為 Activepieces 工作流內(nèi)部的結(jié)構(gòu)化狀態(tài)庫數(shù)據(jù)與 Flow 同處一個(gè)平臺(tái)無需運(yùn)維外部數(shù)據(jù)庫電子表格 UI 降低維護(hù)成本W(wǎng)ebhook 事件天然驅(qū)動(dòng)自動(dòng)化。但它的過濾是內(nèi)存級(jí)的、日期類型不做寫入強(qiáng)校驗(yàn)、并發(fā)批量寫入有競態(tài)邊界因此在高并發(fā)寫入、復(fù)雜 SQL 聚合、強(qiáng)類型約束場景下仍應(yīng)評(píng)估是否將數(shù)據(jù)遷移到外部關(guān)系型數(shù)據(jù)庫再通過既有數(shù)據(jù)庫類 piece 接入。【免費(fèi)下載鏈接】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項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ac/activepieces創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考