Iterate over nested array

Hello,

Thanks for the amazing job you’ve done.

I still have trouble understand loop in n8n.

Here is my scenario :

  • I get data from external api, the shape of data looks like that
[
 {
   id: 1, 
   data: [ {id: a}, {id: b} ]
 }, 
 {
   id: 2, 
   data: [ {id: c}, {id: d} ]
 }
]

I want to make 1 http call for each element in data array, update element with new data and restore updated data in the original object.

The result should looks like that :

[
 {
   id: 1, 
   data: [ {id: a, ...more data}, {id: b, ...more data} ]
 }, 
 {
   id: 2, 
   data: [ {id: c...more data}, {id: d...more data} ]
 }
]

My question is how to execute a node for each element in data array and restore the array with updated data in the original object ?

Thanks

I ended up doing it manually but I’m curious to have feedback about the correct way to handle this scenario with n8n.

Here is a simplify version of my workflow :

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return {...item, moreData: true};"
      },
      "name": "HTTP call",
      "type": "n8n-nodes-base.functionItem",
      "typeVersion": 1,
      "position": [
        820,
        320
      ]
    },
    {
      "parameters": {
        "mode": "mergeByIndex"
      },
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        1220,
        150
      ]
    },
    {
      "parameters": {
        "functionCode": "const inputData =  [\n  {id: 1, data: [{id: 10}, {id: 11}] },\n  {id: 2, data: [{id: 20}, {id: 21}] },\n];\n\nreturn inputData.map((res) => ({json: res}));"
      },
      "name": "Input data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        420,
        130
      ]
    },
    {
      "parameters": {
        "functionCode": "const res = []\nitems.forEach((item) => {\n  item.json.data.forEach((d) => {\n    res.push({...d, parentId: item.json.id})\n  })\n})\nreturn res.map((e) => ({json: e}));"
      },
      "name": "Flatify data with parent id",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        620,
        320
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{ json: {inputData: items} }];"
      },
      "name": "Map input data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        820,
        130
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{json: {updatedData: items}}];"
      },
      "name": "Map updated data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1020,
        320
      ]
    },
    {
      "parameters": {
        "functionCode": "const inputData = item.inputData;\nconst updatedData = item.updatedData;\n\n inputData.forEach((input) => {\n  input.json.data = input.json.data.map((d) => {\n    const matchingData = updatedData.find((ud) => ud.json.id === d.id && ud.json.parentId === input.json.id)\n    return {...matchingData.json}\n  })\n});\n\nreturn inputData.map((d) => d.json);"
      },
      "name": "Final data updated",
      "type": "n8n-nodes-base.functionItem",
      "typeVersion": 1,
      "position": [
        1420,
        150
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Input data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP call": {
      "main": [
        [
          {
            "node": "Map updated data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Final data updated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Input data": {
      "main": [
        [
          {
            "node": "Map input data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Flatify data with parent id",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flatify data with parent id": {
      "main": [
        [
          {
            "node": "HTTP call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map input data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map updated data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    }
  }
}