Function Node Output Data

Hello.

Can someone pinpoint me what am i missing in the following scenario?

I have a javascript code that runs correctly.

https://glot.io/new/javascript

let j=[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
];


let values=j.reduce((o,a)=>{
                    let ini=[];
                    ini.push("(", "NULL", 5, a.DirName, "NOW", ")");
                    o.push(ini);
                    return o;
              },[]);
              
let forInsert = values.join(', ');
let finalInsert = forInsert.replace(/\(\,/g, "(").replace(/\,\)/g, ")");

console.log(finalInsert);

The result is

(NULL,5,mour,NOW), (NULL,5,dmyk,NOW), (NULL,5,oiad,NOW), (NULL,5,deko,NOW), (NULL,5,dvia,NOW)

I want to replicate it in n8n that but i think i am missing something minor and i get stuck.

The code is

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        80,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "let j=[\n{\n\"DirName\": \"mour\"\n},\n{\n\"DirName\": \"dmyk\"\n},\n{\n\"DirName\": \"oiad\"\n},\n{\n\"DirName\": \"deko\"\n},\n{\n\"DirName\": \"dvia\"\n}\n];\n\nreturn j.map(e => { return { json: e } });\n"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        330,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "const mergeValues = $items(\"Function\");\n\nlet values=mergeValues.reduce((o,a)=>{\n                    let ini=[];\n                    ini.push(\"(\", \"NULL\", 5, a.DirName, \"NOW\", \")\");\n                    o.push(ini);\n                    return o;\n              },[]);\n\nlet forInsert = values.join(', ');\nlet finalInsert = forInsert.replace(/\\(\\,/g, \"(\").replace(/\\,\\)/g, \")\");\n\nlet insertArray = [{finalInsert}];\n\nreturn insertArray.map(e => { return { json: e } });\n"
      },
      "name": "Function1",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        620,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Function1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

If you run it the result is

(NULL,5,,NOW), (NULL,5,,NOW), (NULL,5,,NOW), (NULL,5,,NOW), (NULL,5,,NOW)

It misses the DirName.

What am i doing wrong?

Hi @Mulen, I am not entirely sure I understand what you want to achieve here. In the JS code you have provided, finalInsert is a simple String. So you could just write this String into a field of your choice (keeping in mind the n8n data structure). This example workflow runs your code and writes the result in a field of an n8n item:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "let j = [{\n        \"DirName\": \"mour\"\n    },\n    {\n        \"DirName\": \"dmyk\"\n    },\n    {\n        \"DirName\": \"oiad\"\n    },\n    {\n        \"DirName\": \"deko\"\n    },\n    {\n        \"DirName\": \"dvia\"\n    }\n];\n\n\nlet values = j.reduce((o, a) => {\n    let ini = [];\n    ini.push(\"(\", \"NULL\", 5, a.DirName, \"NOW\", \")\");\n    o.push(ini);\n    return o;\n}, []);\n\nlet forInsert = values.join(', ');\nlet finalInsert = forInsert.replace(/\\(\\,/g, \"(\").replace(/\\,\\)/g, \")\");\n\nreturn [{\n  json: {\n    result: finalInsert\n  }\n}]\n\n"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Looking at your example data it seems, however, you want to mix data from two different sources? I’d try to keep it as simple as possible in this case. Iterate through the array from your first function node and build the string step by step. This example returns both a single string and multiple items, depending on your preference:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "let j = [{\n        \"DirName\": \"mour\"\n    },\n    {\n        \"DirName\": \"dmyk\"\n    },\n    {\n        \"DirName\": \"oiad\"\n    },\n    {\n        \"DirName\": \"deko\"\n    },\n    {\n        \"DirName\": \"dvia\"\n    }\n];\n\nreturn j.map(e => {\n    return {\n        json: e\n    }\n});"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "let results = [];\n\n$items(\"Function\").forEach(item => {\n  results.push(`(NULL,5,${item.json.DirName},NOW)`);\n});\n\n// At this stage we have an array of strings looking like [(NULL,5,mour,NOW),(NULL,5,dmyk,NOW),...]\nconsole.log(results.toString());\n\nreturn [{\n  json: {\n    result: results.toString()\n  }\n}];"
      },
      "name": "Return Single Item",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        650,
        100
      ]
    },
    {
      "parameters": {
        "functionCode": "let results = [];\n\n$items(\"Function\").forEach(item => {\n  results.push(`(NULL,5,${item.json.DirName},NOW)`);\n});\n\n// At this stage we have an array of strings looking like [(NULL,5,mour,NOW),(NULL,5,dmyk,NOW),...]\nconsole.log(results.toString());\n\n// Here we map our array to match the n8n data format\nreturn results.map(e => {\n  return {\n    json: {\n      result: e\n    }\n  }\n});"
      },
      "name": "Return Multiple Items",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Return Single Item",
            "type": "main",
            "index": 0
          },
          {
            "node": "Return Multiple Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Hope these examples help you get started :slight_smile:

Depending on your exact input format you might also want to check whether your are able to rid yourself of (all or some) JS code through helper nodes such as Merge or Item Lists.

@MutedJam

From the example i mentioned the goal is to get the output data just like it appears on Function node

[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
] 

I thought by adding on the second Function node this

const values = $items("Function");

I would get the above array but it doesn’t work. The values it gets are like this

values

I want to get the Array as is from the output of Function 1 node.

[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
] 

I think I am a bit lost here. So you don’t want to see (NULL,5,mour,NOW), (NULL,5,dmyk,NOW), (NULL,5,oiad,NOW), (NULL,5,deko,NOW), (NULL,5,dvia,NOW) as the output, neither as individual items nor as a single string?

Can you provide an example of the result you want to see? Proper n8n items like so?

That’d be much simpler:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "let j = [{\n        \"DirName\": \"mour\"\n    },\n    {\n        \"DirName\": \"dmyk\"\n    },\n    {\n        \"DirName\": \"oiad\"\n    },\n    {\n        \"DirName\": \"deko\"\n    },\n    {\n        \"DirName\": \"dvia\"\n    }\n];\n\nreturn j.map(e => {\n    return {\n        json: e\n    }\n});"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "let results = [];\n\n$items(\"Function\").forEach(item => {\n  results.push({\n    json: {\n      field_a: null,\n      field_b: 5,\n      DirName: item.json.DirName,\n      field_d: 'NOW'\n    }\n  });\n});\n\nreturn results;"
      },
      "name": "Return Multiple Items",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        650,
        200
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Return Multiple Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

This also works without JS code (apart from the example data):

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "let j = [{\n        \"DirName\": \"mour\"\n    },\n    {\n        \"DirName\": \"dmyk\"\n    },\n    {\n        \"DirName\": \"oiad\"\n    },\n    {\n        \"DirName\": \"deko\"\n    },\n    {\n        \"DirName\": \"dvia\"\n    }\n];\n\nreturn j.map(e => {\n    return {\n        json: e\n    }\n});"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        200
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "field_a",
              "value": "={{null}}"
            },
            {
              "name": "DirName",
              "value": "={{$json[\"DirName\"]}}"
            },
            {
              "name": "field_d",
              "value": "NOW"
            }
          ],
          "number": [
            {
              "name": "field_b",
              "value": 5
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        650,
        200
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

I’ll try to describe it more clearly.

I have created this script as i said below

let j=[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
];


let values=j.reduce((o,a)=>{
                    let ini=[];
                    ini.push("(", "NULL", 5, a.DirName, "NOW", ")");
                    o.push(ini);
                    return o;
              },[]);
              
let forInsert = values.join(', ');
let finalInsert = forInsert.replace(/\(\,/g, "(").replace(/\,\)/g, ")");

console.log(finalInsert);

The output is

(NULL,5,mour,NOW), (NULL,5,dmyk,NOW), (NULL,5,oiad,NOW), (NULL,5,deko,NOW), (NULL,5,dvia,NOW)

So i want to do it via n8n.

I create a function node which holds the data

Function1

let j=[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
];

return j.map(e => { return { json: e } });

Now the json output of that node is

[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
] 

So far so good.

Now on Function2 node i want to get the Array from Function1 node as is so that i run the script i wrote and the output should be

[
{
"finalInsert": "(NULL,5,mour,NOW), (NULL,5,dmyk,NOW), (NULL,5,oiad,NOW), (NULL,5,deko,NOW), (NULL,5,dvia,NOW)"
}
] 

The thing is on Function2 Node i add

const mergeValues = $items("Function");

let values=mergeValues.reduce((o,a)=>{
                    let ini=[];
                    ini.push("(", "NULL", 5, a.DirName, "NOW", ")");
                    o.push(ini);
                    return o;
              },[]);

let forInsert = values.join(', ');
let finalInsert = forInsert.replace(/\(\,/g, "(").replace(/\,\)/g, ")");

let insertArray = [{finalInsert}];

return insertArray.map(e => { return { json: e } });

But the

const mergeValues = $items("Function");

Does not get the output array from Function1 node as is.

I just want to get the array

[
{
"DirName": "mour"
},
{
"DirName": "dmyk"
},
{
"DirName": "oiad"
},
{
"DirName": "deko"
},
{
"DirName": "dvia"
}
] 

from Function1 node and assign it to a variable in Function2 node

This code inside your Function1 is getting all output items from your Function node though. If you add a console.log(mergeValues); in the line thereafter, you can also see the items in your browser console:
image

Your subsequent mergeValues.reduce does, however, not reference DirName correctly. If you replace a.DirName with a.json.DirName you should get your result string including the DirName:

1 Like

Yes thank you. That was what i was missing.

Thank you for your patience and help!

1 Like