2084 字
10 分鐘
n8n 踩坑筆記:Code 節點無法合併資料?該用 Merge 節點還是 Aggregate?

在 n8n 工作流程中,我遇到了一個看似簡單卻讓人困惑的問題:我想合併兩個 Google Sheets 的資料,直覺上想用 Code 節點處理,結果卻失敗了。

這篇文章記錄我踩坑的過程,以及正確的解決方案。

問題一:為什麼 Code 節點無法合併資料?#

我的錯誤嘗試#

我的工作流程很簡單:

[Google Sheets A] → [Code Node] ← [Google Sheets B]

我想在 Code 節點中把兩個 Sheets 的資料合併成一個陣列,於是寫了這樣的程式碼:

// ❌ 錯誤嘗試:想要同時取得兩個來源並合併
const dataA = $input.all(); // 只能取得其中一個來源!
const dataB = ???; // 無法取得另一個來源
// 原本想這樣合併
return [...dataA, ...dataB];

結果:失敗!

$input.all() 只能取得「主要輸入」,當有兩條線連入時,我根本無法用這個方法同時取得兩個資料源。

嘗試用 $('節點名稱') 解決#

看了文件後,我發現可以用 $('節點名稱').all() 來明確指定節點:

// ❌ 還是不建議這樣做
const sheetsA = $('Google Sheets A').all();
const sheetsB = $('Google Sheets B').all();
// 手動合併
return [...sheetsA, ...sheetsB];

雖然這樣「技術上」可行,但這不是正確的做法!

正確解法:使用 Merge 節點#

n8n 提供了專門用來合併資料的節點:Merge 節點

正確的工作流程應該是:

[Google Sheets A] → [Merge Node] ← [Google Sheets B]
[Code Node]

Merge 節點的設定方式#

  1. 新增 Merge 節點

    • 在工作流程中新增「Merge」節點
    • 將兩個資料源分別連接到 Merge 節點
  2. 選擇合併模式 (Mode)

    常用的合併模式:

    模式說明使用時機範例
    Append單純串接兩個清單合併成一個合併兩個 Google Sheets 的所有資料
    Combine依索引配對兩個清單依順序一對一合併訂單資料 + 對應的物流資料
    Merge By Key依欄位值合併類似 SQL JOIN用戶 ID 合併訂單和用戶資料
    Choose Branch選擇性輸出只保留其中一個分支A/B 測試選擇執行路徑
  3. 實際範例 模式 (最常用)

    假設你有兩個 Google Sheets,想合併所有資料:

    設定步驟:
    1. Mode: Append
    2. 不需要額外設定
    3. 輸出: [來源 A 的所有資料] + [來源 B 的所有資料]

    輸入 1 (Google Sheets A):

    [
    { "name": "產品 A", "price": 100 },
    { "name": "產品 B", "price": 200 }
    ]

    輸入 2 (Google Sheets B):

    [
    { "name": "產品 C", "price": 300 },
    { "name": "產品 D", "price": 400 }
    ]

    Merge 輸出:

    [
    { "name": "產品 A", "price": 100 },
    { "name": "產品 B", "price": 200 },
    { "name": "產品 C", "price": 300 },
    { "name": "產品 D", "price": 400 }
    ]
  4. 實際範例 By Key 模式

    當你需要依據某個欄位值合併資料 (類似 SQL JOIN):

    設定步驟:
    1. Mode: Merge By Key
    2. Merge By Key: userId (指定要比對的欄位)
    3. Output Data: Both Inputs (輸出合併後的完整資料)

    輸入 1 (用戶資料):

    [
    { "userId": 1, "name": "張三" },
    { "userId": 2, "name": "李四" }
    ]

    輸入 2 (訂單資料):

    [
    { "userId": 1, "orderAmount": 500 },
    { "userId": 2, "orderAmount": 800 }
    ]

    Merge 輸出:

    [
    { "userId": 1, "name": "張三", "orderAmount": 500 },
    { "userId": 2, "name": "李四", "orderAmount": 800 }
    ]

Merge 節點的優勢#

  • 原生支援:不需要寫程式碼,透過視覺化介面設定
  • 多種合併模式、Combine、Merge By Key、Choose Branch
  • 視覺化清楚:工作流程更易維護和理解
  • 效能更好:原生實作比 JavaScript 迴圈更快
  • 錯誤處理:自動處理資料型別不符等問題
重要觀念

Code 節點適合用於「參考」其他節點的值來處理資料,而不是用來「合併」多個資料源。如果需要合併資料,請使用 Merge 節點

經驗法則:

  • 需要合併兩個清單 → 用 Merge 節點
  • 需要用另一個節點的值來過濾資料 → 用 Code 節點 + $('節點名稱')

何時用 Code 節點的 $('節點名稱') ?#

$('節點名稱') 語法適合用於這種情境:

// ✅ 正確使用情境:參考另一個節點的「單一值」來處理資料
const products = $input.all(); // 主要資料
// 從另一個節點取得「要排除的分類」
const excludeCategory = $('設定節點').first().json.category;
// 用這個參考值來過濾資料
const filtered = products.filter(item => {
return item.json.category !== excludeCategory;
});
return filtered;

使用場景對比:

需求應使用的方法說明
合併兩個資料源成單一清單Merge 節點✅ 推薦做法
參考另一個節點的單一值來處理資料$('節點名稱').first()✅ Code 節點適用
依條件比對兩個清單$('節點A').all() + $('節點B').all()⚠️ 可行但複雜

問題二 節點的資料為什麼變成 1 筆?#

問題現象#

除了合併資料,我還遇到另一個困惑:當我用 Aggregate 節點處理資料後,明明輸入有 5 筆資料,為什麼在 Code 節點中只看到 1 個項目?

// Aggregate 前:5 筆資料
// Aggregate 後:只有 1 筆?
const data = $('Aggregate').all();
console.log(data.length); // 輸出:1 (而不是預期的 5)

原因 會「打包」資料#

Aggregate 節點的運作方式:

  • 將多筆項目「打包」成單一項目
  • 真正的資料陣列被放在 .json.欄位名稱 裡面

資料結構變化:

// Aggregate 前 (5 筆)
[
{ json: { name: "產品 A", price: 100 } },
{ json: { name: "產品 B", price: 200 } },
{ json: { name: "產品 C", price: 300 } },
// ...
]
// Aggregate 後 (1 筆包裹)
[
{
json: {
products: [ // ← 真正的資料在這裡!
{ name: "產品 A", price: 100 },
{ name: "產品 B", price: 200 },
{ name: "產品 C", price: 300 },
// ...
]
}
}
]

錯誤 vs 正確的處理方式#

// ❌ 錯誤:直接迭代只會執行一次
const data = $('Aggregate').all();
data.forEach(item => {
// 這裡只會執行一次!
console.log(item);
});
// ✅ 正確:先「解包」取出內部陣列
const aggregatedRaw = $('Aggregate').all();
const actualData = aggregatedRaw[0].json.products || [];
// 現在可以正常迭代每一筆資料
actualData.forEach(item => {
console.log(item.name);
});
// 過濾範例
const filtered = actualData.filter(item => item.price > 300);
return filtered.map(item => ({ json: item }));
重要提醒

aggregatedRaw[0].json.products 中的 products 要改成你在 Aggregate 節點「Put Output in Field」設定的欄位名稱。

簡潔寫法:使用解構賦值#

如果你熟悉 JavaScript 解構語法,可以一步到位:

// ✅ 直接解構取出資料陣列
const [{ json: { products: items } }] = $('Aggregate').all();
// items 現在就是真正的資料陣列
return items
.filter(item => item.price > 300)
.map(item => ({ json: item }));

完整實戰範例:結合 Aggregate 和參考節點#

假設你的工作流程是:

  1. 資料經過 Aggregate 打包
  2. 需要參考另一個節點的值來過濾資料
// 步驟 1:解包 Aggregate 資料
const aggregatedRaw = $('Aggregate').all();
const sourceData = aggregatedRaw[0].json.allData || [];
// 步驟 2:取得參考值
const excludeKeyword = $('參考節點').first().json.targetName;
// 步驟 3:過濾資料
const result = sourceData.filter(item => {
if (!item) return false;
const itemKey = Object.keys(item)[0];
return itemKey !== excludeKeyword;
});
// 步驟 4:回傳結果
return result.map(item => ({ json: item }));
除錯技巧

使用 console.log(JSON.stringify(data, null, 2)) 可以清楚看到資料的完整結構,幫助你快速找到問題。

常見陷阱與解決方案#

陷阱解決方案
用 Code 節點合併資料使用 Merge 節點
忘記解包 Aggregate記得存取 .json.欄位名稱
節點名稱拼錯檢查左側節點列表的確切名稱
未檢查空值加入 if (!item) 檢查
欄位名稱錯誤確認 Aggregate「Put Output in Field」設定
重要

只有當 Code Node 設定為「Run Once for All Items」模式時,才能使用 $('節點名稱').all() 語法。

總結:何時用 Code / Merge / Aggregate?#

經過這次踩坑,我整理出這三個節點的正確使用時機:

Merge 節點#

  • ✅ 合併兩個資料源成單一清單
  • ✅ 依 key 值合併資料 (像 SQL JOIN)
  • ✅ 選擇性保留某個分支的資料

Aggregate 節點#

  • ✅ 將多筆資料打包成單一項目
  • ✅ 準備資料傳給 HTTP Request 等節點
  • ✅ 彙總資料

Code 節點 + $('節點名稱')#

  • ✅ 參考其他節點的單一值來處理資料
  • ✅ 複雜的條件判斷和資料轉換
  • 不要用來合併資料 (請用 Merge)

記住這些原則,就能避免像我一樣踩坑了!


參考資料:

n8n 踩坑筆記:Code 節點無法合併資料?該用 Merge 節點還是 Aggregate?
https://laplusda.com/posts/n8n-code-node-merge-vs-aggregate/
作者
Zero
發佈於
2025-12-12
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。