嗨,大家今天過得好嗎?歡迎來到鐵人賽 Day 21。
過去 20 天,我們成功打造了一個完整的「查詢與推薦」系統。前端發送需求 ➔ 後端撈取時價 ➔ AI 推理 ➔ 前端渲染結果。
但如果從一個真實商業產品(SaaS)的角度來看,只會「讀取 (Read)」的系統充其量只是個玩具。真正的商業應用,必須能夠「寫入 (Write)」。我們不僅要讓 AI 產出推薦菜單,還要把這份菜單連同使用者的 Session ID 一起存回 PostgreSQL 資料庫裡,當作歷史訂單或推薦紀錄,以便未來進行數據分析或讓使用者查詢歷史。
今天,我們就要在 n8n 的工作流中,加上這塊最重要的商業邏輯拼圖。
在開始拉節點之前,請確保你的 PostgreSQL 裡面有一張用來存紀錄的表(例如 hardware_history)。它的欄位大概會長這樣:
session_id (字串)budget (整數)purpose (字串)cpu (字串)gpu (字串)total_price (整數)回到我們 n8n 的畫布。目前工作流的最後一站是掛載了 JSON Schema 的 Basic LLM Chain 節點。
請在這個節點的後面,新增一個 PostgreSQL 節點。
Execute Query。INSERT INTO hardware_history (session_id, budget, purpose, cpu, gpu, total_price)
VALUES ($1, $2, $3, $4, $5, $6);
$node 表達式在設定 Query Parameters 時,你會遇到一個問題:cpu 跟 gpu 可以從上一個 AI 節點拿到,但 session_id 跟 budget 是在最前面的 Webhook 節點傳進來的,現在早就被 AI 的 Output 洗掉了,怎麼辦?
很多新手會在前面加一堆 Edit Fields 節點把變數保留下來。但在 n8n,你有一招更優雅的寫法。
在輸入參數時,你可以直接指定「去哪個節點抓資料」。例如:
{{ $node["Webhook"].json.body.budget }}
{{ $json.cpu }}
透過 $node["節點名稱"],你可以隨心所欲地跨越時空,拿取工作流中任何一個步驟的歷史資料!把這 6 個參數設定好,回寫機制就完成了。
當你開心地把 Postgres INSERT 節點接好,按下執行,打開 iOS App 測試...
恭喜你,App 又 Crash 變白畫面了!
為什麼?讓我們回想一下 Day 11 設定的 Webhook 節點,當時 Respond 的選項設定為 When Last Node Finishes (當最後一個節點完成時回傳)。
原本最後一個節點是 AI,它完美吐出 JSON 給 App。但現在,最後一個節點變成了 Postgres INSERT!
Postgres INSERT 成功後,預設只會吐出類似 [ { "success": true } ] 的訊息。於是,n8n 就把這句 success 傳回給 Swift,Swift 的 JSONDecoder 發現沒有 cpu 也沒有 gpu,當場崩潰。
為了精準控制到底要回傳什麼給前端,我們需要使用 n8n 專門的 Response 節點。
Respond 選項改為 Using 'Respond to Webhook' Node。Respond to Webhook 節點。Respond With 選擇 JSON。Response Body 中,我們要把被 Postgres 洗掉的 AI 資料叫回來。一樣使用跨節點表達式,填入:{{ $node["Basic LLM Chain"].json }}
現在,工作流變成了:[Webhook 接收] ➔ [資料庫撈價] ➔ [AI 推理] ➔ [寫入歷史 DB] ➔ [指定回傳 AI 產出給前端]。
再次打開你的 iOS App,送出預算。
App 順利彈出精美的結果卡片(Swift 成功解析)。
接著,打開你的資料庫軟體 (如 pgAdmin) 查詢 hardware_history 表,你會看到剛剛那筆配單紀錄,已經安安靜靜地躺在資料庫裡了!
今天我們成功實作了資料庫回寫,並且學會了使用 $node 表達式跨節點抓資料,以及用 Respond to Webhook 精準控制 API 的回傳內容。
有了歷史紀錄後,我們的 App 就不再是一次性的工具了。明天,我們要再次利用 Vibe Coding 切換回 SwiftUI 戰場。既然資料庫裡有紀錄了,我們就來做一個「歷史訂單列表頁面」,把使用者過去拜託 AI 配過的菜單全部拉出來展示!
我們 Day 22 見!