Mapping Two array members

Hey , Guys!
I’m doing a workflow , which takes a query from Metabase and returns an object with arrays. The first array , which is called “rows” contains the values (name,products,address etc) and the second one is called “cols” and contains the keys (the names of the columns). Is there a way I can map the [0] member of “cols” to refer to the [0] element of “rows”. Here’s a screenshot of the outcome of the metabase question.

Thanks a lot!
Pavel

Check the example below:

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [\n  {\n    json: {\n      data: {\n        rows: [\n          [\n            'ricardo',\n            'espinoza'\n          ]\n        ],\n        cols: [\n          {\n            display_name: 'first_name'\n          },\n          {\n            display_name: 'last_name'\n          }\n        ]\n      }\n    }\n  }\n]"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        550,
        300
      ],
      "notesInFlow": true,
      "notes": "Mockup data"
    },
    {
      "parameters": {
        "functionCode": "const results = [];\n\nconst columns = items[0].json.data.cols.map(column => column.display_name)\n\nconst rows = items[0].json.data.rows;\n\nfor (const row of rows) {\n  const result = {};\n  for (const [index, column] of columns.entries()) {\n      result[column] = row[index]\n  }\n  results.push({ json: result })\n}\n\nreturn results;"
      },
      "name": "Function1",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        800,
        300
      ],
      "notesInFlow": true,
      "notes": "Map data"
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Function1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Thanks, Ricardo!
I have one more trivia question: Do you know what JS dialect is n8n using?

Of course. Not sure what you mean with dialect. Can you please elaborate?

If you mean the syntax in the Function node, it is the body of a JS function combined with n8n-native data structures and methods.

2 Likes

Hi @PavelEfremov! Very valid question about the JS dialect, and I’m curious to why you’re asking. Is there something you’ve tried that’s not working as expected?

HI @sirdavidoff ! I’m just curious about it , because I’m studying vanilla JS and it’s quite different from it!

Got you — thanks!

Hi I was wondering the dialect same (not a dev or js connoisseur).

Is it ECMAScript 6 or something similar?
Or is it Typescript? :thinking:

@ivov the link to the body is the wrapper in which the code is executed, right?

So since this is TypeScript the function should also be TypeScript?

Trying to find a way to get the right developer to help me with actual “code”.

No TypeScript is sadly not supported.

What is supported exactly, depends on the Node.js version you are using to run n8n. The default n8n Docker image uses Node.js v14.15.

The reason for that is that n8n does not do much except running the supplied code with Node.js via the package vm2.

Hope that is helpful!

1 Like

To add to Jan, n8n is written in TS and transpiled into the JS that gets executed. In the Function node input box, you enter a string that is the body of a param-less JS function, which gets executed in a VM2 sandbox, so if you use TS-specific constructs, it will error out.

function myFunction() {
  // your input
}

myFunction();

Bear in mind the above restrictions about data structures and methods still apply. At first glance this is what might make it look different from vanilla JS.

1 Like

Thank you. So e.g. to make a split in batches work, I’d have to use the following format:

2021-04-14 at 16.06

which means in ricardos example that the json part of "functionCode": "return [\n {\n json: is super is super important?

Exactly, the json property is not optional - what you return needs to satisfy the Function node’s validators.

1 Like

Btw. you can find more information about the internal data structure here.

1 Like

Thanks so much @ivov and @jan !
It finally makes sense :slight_smile: .

If I work with an external API and it returns multiple projects or mixed format, then I can wrap it inside n8n specific json/binary data structure and connect it to the core n8n nodes.

Okay, I still don’t really understand why it works sometimes and sometimes doesn’t.
Is there a way to get more debug info than just checking the response between the two nodes?
“Split in batches” node is sometimes not updating.
I’d like to know exactly what is sent between the two nodes.

Sorry I do not understand. If you open a node and look at its data then you see exactly the data that the node does output and which does get send into the next node.

Can you please also elaborate what you mean with ““Split in batches” node is sometimes not updating.”.

Thanks!

Hi Jan,
I think I understand it now. It was how data is flowing while still debugging with having a “split in batches” loop in the middle with the different way how to trigger each node:

  • Open Node > Execute workflow
  • Click on “>” icon on workflow
  • Click on “Execute Workflow” button (–> this appears to be the ideal way to test) when a loop is involved.

Thanks for your help and sorry for being a bit off topic here :slight_smile: