Item 是什麼?資料怎麼在節點間流動
n8n 最重要、也最容易被略過的觀念就一個字:item。搞懂 item 之後,「為什麼我的 workflow 只跑一次不是五次」「為什麼 Slack 節點傳了 100 遍」「為什麼 Expression 顯示 undefined」都會變合理。這章一次講清楚,之後每一章都會回來用。
為什麼要搞懂 item
第 8 章做完那個「早上把行事曆推 Slack」的 workflow 之後,你大概會發現幾件怪事:
- Google Calendar 節點跑一次讀回五個事件,Slack 節點就自己傳了五次訊息——沒人叫它 for-loop 啊?
- Expression 面板打
{{ $json.summary }}明明有值,換成{{ $json.items[0].summary }}就undefined。 - Google Sheet 讀回一個空表,下游全部節點直接被跳過——連錯誤都沒噴,就是不跑。
- 用 Set 節點加了一個欄位,結果 output 面板一次跑出五列,不是預期的一列。
這些現象背後都是同一件事:n8n 節點跟節點之間傳的不是一團 JSON,是一「列」一「列」的 item。跟 Zapier 把這件事藏起來不同,n8n 把 item 直接攤在你眼前——這也是它比 Zapier 強、但初學者比 Zapier 難的核心原因。
item 就是「一筆資料」,像 Excel 一列
最好用的比喻:每個節點的 output 就是一份 Excel 表格,表格的每一列就是一個 item。
| Excel 用語 | n8n 用語 | 實際長怎樣 |
|---|---|---|
| 一整份表格 | 節點的 output(一個 array) | [ {...}, {...}, {...} ] |
| 一列 | 一個 item | { name: "Elmo", age: 30 } |
| 一欄 | item 裡的一個 field | name、age |
| 一格 | 某個 item 的某個欄位值 | "Elmo" |
然後最關鍵的規則:下一個節點會對「每一個 item」各跑一次。所以 Google Sheet 讀回 100 列 → Slack 節點就會傳 100 次訊息。這不是 bug,是 n8n 的核心行為,官方文件叫item-based execution。
一個 item 內部有哪些「隔間」
一個 item 不是純 JSON,而是有幾個固定隔間的物件。你 99% 只會用第一個,但另外兩個知道存在會少踩坑。
| 隔間 | 放什麼 | 什麼時候會用到 |
|---|---|---|
json | 主要資料,一個純 JSON 物件。這是你 99% 時間在讀的地方。 | 幾乎所有 workflow。 |
binary | 附加的檔案內容(PDF、圖片、CSV 等 binary data)。 | Gmail 附件、Google Drive 下載、API 回傳檔案。 |
pairedItem | 記錄「這個 item 是從上游哪個 item 來的」,用於 Merge 節點對齊。 | 用 Merge 節點合流的時候。多數情況 n8n 自動填。 |
用程式碼看一個 item 完整長這樣:
{
"json": {
"name": "Elmo",
"age": 30,
"email": "[email protected]"
},
"binary": {
"attachment": {
"mimeType": "application/pdf",
"fileName": "invoice.pdf",
"data": "..."
}
},
"pairedItem": { "item": 0 }
}
所以下一個節點要抓 name 這個欄位,路徑是 $json.name——注意是 $json.name 不是 $json.json.name,n8n 幫你把外面那層 json 拆掉了,讓 Expression 短一點。
在 Expression 裡抓資料的四個核心寫法
節點欄位切成 Expression 模式(欄位右上角那個齒輪或 = 標記)之後,就是進到 Expression 世界。抓 item 資料只有這四種寫法要背,其他都是變化:
| 寫法 | 意思 | 什麼時候用 |
|---|---|---|
{{ $json }} | 當前 item 的整包 JSON。 | 想看整包長怎樣、傳給下游整包。 |
{{ $json.field }} | 當前 item 的某個欄位。 | 最常用,例:{{ $json.summary }}、{{ $json.email }}。 |
{{ $json['field with space'] }} | 欄位名有空格或中文用中括號寫。 | API 回來的欄位叫 User Name、訂單編號時。 |
{{ $('Google Sheets').item.json.field }} | 抓上游指定節點的資料(不是上一個節點)。 | 跳過中間節點抓兩三站前的資料。 |
$('節點名稱') 就是「用節點名找到上游那個節點的 output」的意思。節點名字是你在 canvas 上看到的那個(雙擊節點可以改)。這樣寫的好處是——就算中間插了一堆 Set / IF,你還是能直接回頭抓原始資料。
同一個節點會跑幾次?兩種模式
「這個節點會跑幾次」這件事,被兩個因素決定:input 有幾個 item 和 節點的 Execute Once 設定。多數內建節點的預設行為是「input 有幾個 item 就跑幾次」,但這是可以改的。
| 模式 | 行為 | 誰是這樣 |
|---|---|---|
| 對每個 item 各跑一次(預設) | Input 有 N 個 item → 節點會跑 N 次 → output 通常也是 N 個 item。 | 大部分整合類節點(Slack、Gmail、HTTP Request 打 API 等)。 |
| 吃全部 item 一次處理完 | Input 有 N 個 item → 節點只跑一次拿到整份 array → 你在裡面決定要 output 幾個。 | Set、Aggregate、Item Lists、Code node(可切)、Sub-workflow(可切)。 |
要看/改一個節點是哪一種:點節點打開設定 → 頂端切到 Settings 分頁 → 找 Execute Once 這個 toggle。開啟後這個節點無論 input 幾個 item,都只用第一個 item 跑一次,其他丟掉。
三個節點的資料流動實例
看抽象概念看到頭暈?拿最簡單的 3 節點 workflow 走一次就懂了:Manual Trigger → Google Sheets (Read) → Slack (Send)。假設 Google Sheet 裡有 5 列聯絡人。
| 階段 | 節點 | Input items | 做什麼 | Output items |
|---|---|---|---|---|
| 開頭 | Manual Trigger | —(沒有 input) | 手動按 Execute 觸發。 | 1 個空 item:[ {} ] |
| 中間 | Google Sheets (Read Rows) | 1 個 item | 對這 1 個 item 跑一次,去 Sheet 讀回 5 列。 | 5 個 items:[{row1}, {row2}, ...] |
| 結尾 | Slack (Send Message) | 5 個 items | 對每個 item 跑一次 send → 傳 5 次訊息。 | 5 個 items(每次 send 的結果) |
看出來重點了嗎——資料筆數是被中間那個節點放大的。Manual Trigger 只丟 1 個空 item 進去,Google Sheets 把它「展開」成 5 個 items,Slack 就自動被連跑 5 次。整個流程沒有一行 for-loop 程式碼,全靠 item 觀念自動展開。
看 output 面板讀 item 的三種檢視
節點按 Execute step(單獨跑這個節點)或整個 workflow 跑完之後,畫面右邊的 output 面板會顯示這個節點吐出的 items。頂端有三個檢視模式可以切,各有各的場合:
| 檢視 | 看起來像 | 什麼時候用 |
|---|---|---|
| Table(表格) | Excel 表格,欄位是 column、item 是 row。 | 快速看每個 item 的值、比對筆數對不對。這是預設檢視。 |
| JSON | 原始 JSON 陣列,可以展開/收合物件。 | Table 顯示不下(欄位太多/巢狀結構)、要複製整包貼到別的地方。 |
| Schema | 樹狀的欄位結構圖,只顯示欄位名與型別,不顯示值。 | 寫 Expression 前必看——知道有哪些欄位可以抓、路徑怎麼寫。 |
面板頂端還會顯示「N items」那個數字——這是你 debug 最常看的一個數字。跟你預期不一樣就代表這個節點出事了,往上游追。
Table 檢視每一列前面有個小數字(0、1、2...)就是 item index。抓「第一個 item 的某個欄位」就是 $json.field(當前那一次 iteration 的 item);不是 $json[0].field——這是初學者最常犯的錯之一。
為什麼我的 workflow 只跑 1 次不是 5 次?
這是新手第一週最常問的問題。原因永遠是三個之一,用Executions 逐節點看 item 數量就能定位:
| 原因 | 症狀 | 怎麼確認 |
|---|---|---|
| A:Trigger 只吐 1 個 item | Schedule Trigger、Manual Trigger 預設每次觸發都只丟 1 個空 item。你以為它會「自動連跑 5 次」是誤解。 | Trigger 節點的 output 面板看 items 數量。 |
| B:某節點被設 Execute Once | 上游有 5 個 items,這個節點只跑 1 次就結束——很可能是你或別人不小心開了 Settings → Execute Once。 | 逐節點看 output items 數量,找那個「從 5 變 1」的節點。 |
| C:Expression 抓錯層級 | 你以為 $json.items 是把 items 展開,但其實它只是抓「當前 item 裡叫 items 的欄位」——那個欄位是個陣列,不是 n8n 的 items 概念。 | Schema 檢視看該節點 output 結構,判斷 items 是真的多個 item 還是一個 item 裡面有個叫 items 的陣列。 |
C 這個很坑:「n8n 的 items」跟「JSON 裡剛好叫 items 的欄位」是兩件事。API 常常回傳長這樣:
{
"total": 5,
"items": [
{ "id": 1, "name": "A" },
{ "id": 2, "name": "B" },
...
]
}
整包被 n8n 當成一個 item(因為 API 回傳就是一包)。要把 items 陣列展開成 5 個 n8n items,需要用 Split Out 節點(第 16 章)指定 items 這個欄位。展開後才會變成 5 個 item,下游節點才會被連跑 5 次。
binary data 什麼時候會用到
多數業務類 workflow 完全不會碰到 binary。只有涉及「檔案本身」的節點才會產生 binary:
- Gmail Trigger 抓到有附件的信 → 附件在
binary.attachment_0、binary.attachment_1... - Google Drive Download → 檔案內容在
binary.data。 - HTTP Request 收到 PDF/圖片回應,且 Response Format 選 File → binary。
- Read/Write Binary File(self-host 才有意義)。
看 binary 要切到 output 面板的 Binary 分頁(跟 Table / JSON / Schema 平行的第四個分頁,有 binary 才會出現)。裡面會列每個 binary 的 mime type、檔名、大小,圖片還可以預覽。
$json、把 $binary 清掉;(2)避免不必要的 Execute Workflow 傳遞(sub-workflow 會複製一份)。常見卡關
-
Expression 顯示
undefined兩個可能:(1)欄位名打錯——切 Schema 檢視看真實欄位名(大小寫、有沒有空格、有沒有前綴
data.)。(2)上游節點根本沒跑成功——那個節點的 output 面板是空的或紅色。先修上游再管 Expression。 -
節點跑 100 次但你只想跑 1 次
上游有 100 個 items 的緣故。三個做法選一個:(a)在中間插 Aggregate 節點把 100 個聚合成 1 個;(b)用 Code node(第 20 章)寫
return [ { json: { all: $input.all() } } ];(c)如果只想拿第一筆,該節點 Settings 開 Execute Once——但注意這是「只拿第一筆」不是「合併全部」。 -
Merge 節點吐出來筆數對不上
Merge 有四個 mode,選錯結果差很多:Append(頭接尾,A 3 個+B 2 個=5 個)、Combine(再切三個子選項:Matching Fields 靠欄位值比對像 SQL join、Position 同 index 湊一對、All Possible Combinations 笛卡兒積 A 3 個×B 2 個=6 個)、SQL Query(1.49.0+,直接寫 SQL 湊)、Choose Branch(只挑一邊的資料吐出)。舊版文件把 All Possible Combinations 叫 Multiplex,新版已經改名,看到別人 workflow 用舊稱不用慌。用之前先想清楚要哪一種,第 16 章會拆更細。
-
節點吃到 0 個 item 直接被跳過
n8n 的行為:input 是空 array 時,節點不會跑。這是刻意的(不用寫 empty check)但初學者會誤以為節點壞了。往上游追是誰吐了 0 個——通常是(a)IF 節點兩個分支都沒過、(b)Google Sheet Read 沒讀到資料、(c)過濾節點把全部濾掉。
-
Set 節點跑完 item 數量不對
Set 節點預設對每個 item 各跑一次(保持 item 數量不變),這是對的。如果你發現 5 進 5 出但欄位跑掉,通常是 Set 的模式選了「Keep Only Set」把原欄位砍光了——改成「Include All Fields」或「Include Selected Fields」試試。第 18 章會完整拆 Set 節點。
-
Expression 顯示的預覽跟實際跑出來不一樣
Expression 編輯器預覽用的是「上游節點上一次跑的 output」——如果上游還沒跑或跑錯了,預覽就是舊值。解法:對上游節點按 Execute step 跑一次讓它產生新 output,再回來看 Expression 預覽。
常見問題
Zapier 也有這個 item 觀念嗎?
一次能吃多少 item?有上限嗎?
binary 資料會佔記憶體嗎?
怎麼看到 workflow 實際跑了多久、每個節點花多久?
可以只讓 workflow 對「某幾個 item」跑而不是全部嗎?
$json 跟 $input.all() 差在哪?
$json 是「當前這一輪 iteration 的那個 item 的 json」——因為節點被連跑 N 次,每次的 $json 都指不同的 item。$input.all() 拿的是「這一個節點吃到的全部 items 的 array」(回傳 Array,各成員是完整 item,含 .json / .binary)。Expression 也能呼叫,但實務上最常在 Code node(第 20 章)用——因為 Code node 通常設成一次處理全部。相關姊妹:$input.first()、$input.last()、$input.item。