n8n Notion 同步模板拆解:跨工具資料自動流轉的設計邏輯
把一個 n8n Notion 同步模板拆開來看,從 Trigger、資料映射到去重邏輯逐節點解析,理解跨工具資料自動流轉背後的設計思路,看完你也能自己改。
很多人裝了 n8n、抓了一個 Notion 同步模板,跑起來能動,但問一句「為什麼這樣接?」就答不出來。模板會用,不代表你懂它的設計邏輯。一旦來源換成別的工具、欄位對不上,你就卡死了。
這篇我們把一個典型的 Notion 同步模板整個拆開,一個節點一個節點看它在幹嘛、為什麼要這樣排。看完你不只會用這個模板,是能自己改、自己接別的來源。
這個模板要解決什麼問題
先講情境。最常見的 Notion 同步需求是這幾種:
- 表單回覆(Google Forms / Typeform)自動進 Notion 資料庫
- 別的資料庫(Airtable、Google Sheets)的資料定時同步到 Notion
- Notion 內容變動後,反向更新到其他系統
我們拆的這個模板做的是第二種:把一個外部資料來源,定時、去重、增量地同步進 Notion 資料庫。這是跨工具資料流轉裡最具代表性的一種,搞懂它,其他變形都是換湯不換藥。
整個模板的節點結構長這樣:
Schedule Trigger → 讀取來源資料 → 查詢 Notion 現有資料
→ 比對去重 → 分流(新增 / 更新)→ 寫入 Notion → 記錄結果
別急著抄。每一段都有它存在的理由,我們一段一段看。
第一段:Trigger 為什麼用 Schedule 不用 Webhook
模板開頭是一個 Schedule Trigger,設定每小時跑一次。
很多新手第一個疑問是:為什麼不用 Webhook 即時觸發?答案是來源工具的能力決定觸發方式。
- 如果來源(例如 Airtable)支援 webhook,你可以即時觸發,資料一變就同步。
- 如果來源只能用 API 拉(例如某些舊系統、CSV 匯出),就只能定時輪詢(polling)。
這個模板選 Schedule,是因為它要相容「來源不一定有 webhook」的情況。代價是有延遲(最多差一個輪詢週期),好處是穩定、不依賴來源推送。
設計重點:Schedule 的間隔不是越短越好。間隔太短會把 Notion API 的 rate limit 吃光(Notion 是每秒平均 3 次請求)。一小時一次對多數同步場景夠用了。
第二段:讀取來源資料,為什麼要先排序
接著是來源讀取節點。這裡有個容易被忽略的細節:模板在拉資料時,用更新時間(last edited time)做了排序,而且只拉最近一段時間的。
為什麼不一次拉全部?
因為全量同步既慢又浪費。如果你的來源有一萬筆資料,每次都全拉、全比對,跑一次要好幾分鐘,還會狂打 API。增量同步的核心思路是:只處理「上次同步之後有變動」的資料。
模板的做法是用一個變數記住「上次同步時間」,這次只拉這個時間之後被改過的資料。這就是增量同步的骨架。
第三段:查詢 Notion 現有資料,準備去重

這是整個模板最關鍵、也最多人接錯的一段。
同步的本質問題是:這筆來源資料,在 Notion 裡到底是「新的」還是「已經有了」? 答對了才知道要新增還是更新;答錯了就會產生一堆重複資料。
模板的解法是設一個唯一鍵(unique key)。通常是來源資料的某個 ID 欄位(訂單編號、email、原始系統的主鍵),把它存進 Notion 的某個 property。
去重那一節做的事是:拿來源這筆的唯一鍵,去 Notion 資料庫查詢有沒有同樣鍵值的頁面。
查 Notion:filter property "external_id" = 來源這筆的 id
→ 有結果 → 這是「更新」
→ 沒結果 → 這是「新增」
為什麼不用 Notion 頁面標題去比對? 因為標題會重複、會被人手動改。唯一鍵必須是穩定、不會變、來源端保證唯一的欄位。這是去重邏輯能不能成立的地基。
第四段:分流,IF 節點的真正用途
查完之後,模板用一個 IF 節點做分流:查到 = 走更新路線,查不到 = 走新增路線。
這裡的設計邏輯值得講一下。為什麼要分流,不能一律用「upsert」一個節點搞定?
Notion API 沒有原生的 upsert(有就更新、沒有就新增)。它的 Create Page 和 Update Page 是兩個不同的操作,需要的參數也不同:
- 新增:給資料庫 ID + 所有 property 值
- 更新:給「頁面 ID」+ 要改的 property
更新需要頁面 ID,而這個 ID 是上一段查詢才拿得到的。所以分流不是為了好看,是 API 結構逼你必須分。看懂這點,你就懂為什麼模板非得多繞這一圈。
第五段:資料映射,最髒但最重要的活
兩條路線最後都要寫進 Notion,這時要做欄位映射(field mapping)——把來源的欄位對應到 Notion property。
這段沒有捷徑,但有原則:
- 型別要對齊。Notion 的 property 有型別(Title、Rich text、Number、Date、Select、Multi-select…)。來源的字串要塞進 Number property 會報錯。日期格式要轉成 ISO 8601。
- Select / Multi-select 要處理新值。如果來源出現一個 Notion 還沒有的選項,要嘛先建好選項,要嘛用 API 允許動態建立。
- 空值要明確處理。來源是空的,你是要寫空字串、跳過、還是填預設值?模板通常會用表達式
{{ $json.field || "" }}之類兜底。
映射這段是整個模板最容易壞、最需要照你自己資料改的地方。其他節點可以照抄,這段不行。
第六段:寫入後記錄結果,給「下次同步」用

最後一段常被新手刪掉,但它其實是增量同步的閉環。
模板在寫完之後,會更新「上次同步時間」這個變數(存進 n8n 的 static data、或一個外部記錄)。下次 Schedule 觸發時,第二段就靠這個時間決定要拉哪些資料。
少了這一段,你的「增量」同步就退化回每次都拉固定一段時間,要嘛漏資料、要嘛重複處理。這個記錄節點看起來不起眼,卻是讓整個流程能持續正確運轉的關鍵。
把設計邏輯抽出來:可以套到任何同步場景
拆完這個模板,你會發現它的骨架其實跟「Notion」沒太大關係。同樣的設計邏輯可以套到任何跨工具同步:
| 階段 | 設計問題 | 對應節點 |
|---|---|---|
| 觸發 | 來源能 push 還是只能 poll? | Schedule / Webhook |
| 讀取 | 全量還是增量? | 帶時間過濾的讀取 |
| 識別 | 怎麼判斷新 vs 舊? | 唯一鍵 + 查詢 |
| 分流 | 目標 API 支援 upsert 嗎? | IF + 新增/更新 |
| 映射 | 型別、空值、新選項怎麼處理? | Set / 表達式 |
| 閉環 | 下次怎麼知道從哪繼續? | 記錄同步狀態 |
把來源換成 Airtable、目標換成 Google Sheets,這六個問題的答案會變,但問題本身不變。這才是模板拆解真正要帶走的東西——不是這 7 個節點怎麼接,是這 6 個設計問題怎麼回答。
自己改的時候,最常踩的三個坑
- 唯一鍵選錯。用了會變動的欄位當鍵,結果同一筆資料每次都被當成新的,狂增重複頁面。先確認你的鍵真的穩定且唯一。
- 忽略 Notion rate limit。資料量一大,沒做批次或延遲,請求被擋,同步跑一半掛掉。需要時加 batch + wait。
- 映射沒處理空值與型別,一筆髒資料就讓整條 workflow 報錯中斷。在寫入前加一個驗證或清洗節點,比事後救火便宜。
小結
一個 Notion 同步模板會跑很簡單,但要看懂它「為什麼這樣設計」,得拆到節點層級,問清楚每一段在回答哪個設計問題。觸發方式由來源能力決定、去重靠穩定唯一鍵、分流是被 API 結構逼出來的、映射要照自己資料改、最後別忘了記錄同步狀態做閉環。
把這六個問題裝進腦袋,下次拿到任何同步模板,你都能一眼看穿它的骨架,也能放心地改成自己要的樣子。
想直接拿可用的 n8n 模板來改,少走前面這些彎路,可以看看 N8NMarket 整理的工作流模板,每個都附節點說明,照著拆比從零接快很多。