在迴圈內合併(附加)

Hello n8n community!

I have searched the documentation but did not find a successful answer to my problem.

The use case

I’m processing a list of customer records. Each customer has a contacts array containing items of different types (e.g. phone, email). My goal is to:

  1. Split the contacts array into individual items
  2. Apply a different mapping depending on the contact type (e.g. phone numbers need to be parsed and reformatted, emails pass through directly)
  3. Re-aggregate all mapped contacts back into a single array
  4. Merge that array back into the original customer item to build the final payload

The workflow

The Merge (append) node works inside a loop when the Aggregate is the last node. However, adding a Merge (combine by position) after the Aggregate — which is necessary to reassemble the contacts back into the customer item — breaks the loop entirely.

Test data:

{
  "data": [{
  "firstName": "John",
  "lastName": "Doe",
  "contacts": [
    {
      "type": "phone",
      "value": "+33652252525"
    }
  ]
},
{
  "firstName": "Mary",
  "lastName": "Doe",
  "contacts": [
    {
      "type": "email",
      "value": "marydoe@example.com"
    }
  ]
},
  {
  "firstName": "John",
  "lastName": "Smith",
  "contacts": [
    {
      "type": "email",
      "value": "johnsmith@example.com"
    },
      {
      "type": "phone",
      "value": "+33652252526"
    }
  ]
}]
}


Workflow

Information on your n8n setup

  • n8n version: 2.20.9
  • Database (default: SQLite): PostgrSQL
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker

歡迎 @thomaslc 加入我們的社群!我是 Jay,我是 n8n 認證創作者。

在 SplitInBatches 迴圈內的 Merge(按位置合併)節點會因為它需要兩個輸入同時到達而出現問題 - 但在迴圈內,每次迭代只有一個分支是活躍的。它不是為那種模式而設計的。

最乾淨的修復方法是跳過內部迴圈 + Merge,改為在每個客戶的單一 Code 節點中處理完整的聯絡人轉換。像這樣:

const contacts = $json.contacts;
const mapped = contacts.map(c => {
  if (c.type === 'phone') {
    return { type: 'phone', value: c.value.replace(/\s/g, '') };
  }
  return c;
});
return [{ json: { ...$json, contacts: mapped } }];

這會在外部迴圈的每個項目中執行,就地轉換聯絡人陣列,並直接輸入到最終的有效負載 - 不需要內部迴圈或 Merge。

有趣的限制。您可以使用程式碼節點(如前面所回答的)或甚至使用包含 JS 的編輯欄位節點來簡化工作流程。另一個選項是將迴圈功能傳入子工作流程,並合併子工作流程輸出。

最簡潔的做法是使用單個程式碼節點在一次執行中完成這四個步驟,完全跳過迴圈:

return items.map(item => {
  const mapped = item.json.contacts.map(c => {
    if (c.type === 'phone') return { ...c, value: c.value.replace(/\D/g, '') };
    return c; // email passes through
  });
  return { json: { ...item.json, contacts: mapped } };
});

這樣做可以避免迴圈合併衝突,因為你是內聯轉換陣列。Merge(按位置組合)中斷迴圈是預期的行為 - n8n 迴圈對中途聚合的處理不太好。如果你需要保持基於節點的方法,可以透過 Execute Workflow 將每個已處理的客戶傳遞到子工作流中,並在所有執行完成後聚合結果。

你好 @nguyenthieutoan@njogued

感謝你們的意見回饋!我之所以使用迴圈,是因為我使用了自訂節點,例如電話檢查節點。程式碼節點無法取代它。

最後我做的是建立一個子工作流程,使用「為每個項目執行一次」選項來呼叫它。

@thomaslc,歡迎!

我查看了關於這些項目的文檔,根據我的理解,這與 n8n 保持項目上下文的方式有關。當你使用 Split Out、Loop Over Items、Merge 和 Aggregate 時,它需要保留或重建每個聚合聯絡人與原始客戶之間的連結。如果項目的數量或順序不完全相同,Merge combine by position 可能會破壞這個邏輯。

以下是可以幫助你的文檔: