Function to GroupBy and Unique

Hi all, hope you can help me once again with your javascript skills.

I have a JSON output from an API that I would like to group by field “Data Subject Type Name” (marked in Red in the image), and also list as its properties the unique values of “Data Element Name” (marked in Blue). In other words, find the unique “Data Subject Type Name” and also find their unique “Data Element Name”.

So the output would be a reduced list which I can act on moving forward, please.

Thank you

Not sure If I understood well. Given the input you provided, should the output be as below?

{
    "Customers": [
        "Razao social", "Phone Numbers",
    ],
    "Employees": [
        "E-mail-profissional"
     ],
}

Yes it is correct.
thx

The example below should do it:

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [\n    {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n        {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element2'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Parlamentares',\n        \"Data Element Name\": 'element1'\n      }    \n    }\n]"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        560,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "\nconst types = {};\n\nfor (const item of items) {\n  if (types[item.json[\"Data Subject Type Name\"]] === undefined) {\n      types[item.json[\"Data Subject Type Name\"]] = [];\n      types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n  } else {\n    types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n  }\n}\n\nreturn [{ json: types }]"
      },
      "name": "Function1",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        800,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Function1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Ricardo, first of all thank you so much for the help.
It worked and the results are below.

The results include duplicate items, so if we can have a way to eliminate them in this same function node, or maybe in the next one, please let me know. Thanks again

[ { "Customers": ["Business Unit / Division","Certidão de Nascimento","CNPJ","Comprovante de Endereço","Comprovante de estado civil","CPF","Date of Birth","Declaração de IRPF","E-mail profissional","Endereço comercial","Estado Civil","Filiação a sindicato","Formação","Full Name","Gênero","Home Address","informações de cônjuge","Informações Societárias","Job Title / Role","Local de nascimento","Marital Status","National Identification Number","Nationality","Office Location","Personal Email","Phone Numbers","Profissão","Razão social","Records of Personal Properties","RG","Signature","Telefone profissional","Business Unit / Division","Certidão de Nascimento","CNPJ","Comprovante de Endereço","Comprovante de estado civil","CPF","Date of Birth","Declaração de IRPF","E-mail profissional","Endereço comercial","Estado Civil","Filiação a sindicato","Formação","Full Name","Gênero","Home Address","informações de cônjuge","Informações Societárias","Job Title / Role","Local de nascimento","Nationality","Office Location","Personal Email","Phone Numbers","Profissão","Razão social","Records of Personal Properties","RG","Signature","Telefone profissional","CNPJ","E-mail profissional","Endereço comercial","Full Name","Informações Societárias","Job Title / Role","Office Location","Phone Numbers","Razão social","Telefone profissional","CNPJ","Comprovante de Endereço","E-mail profissional","Endereço comercial","Filiação a sindicato","Full Name","Informações Societárias","Job Title / Role","Office Location","Personal Email","Phone Numbers","Purchasing Tendencies","Razão social","Telefone profissional","Business Unit / Division","CNPJ","Comprovante de Endereço","Declaração de IRPF","E-mail profissional","Endereço comercial","Filiação a sindicato","Formação","Full Name","Home Address","informações de cônjuge","Informações Societárias","Job Title / Role","Office Location","Personal Email","Phone Numbers","Profissão","Razão social","Records of Personal Properties","Telefone profissional","CNPJ","E-mail profissional","Personal Email","Phone Numbers","Razão social","CNPJ","E-mail profissional","Filiação a sindicato","Razão social","Telefone profissional","Business Unit / Division","CNPJ","E-mail profissional","Endereço comercial","Full Name","Job Title / Role","Phone Numbers","Profissão","Razão social","Telefone profissional","Business Unit / Division","CNPJ","E-mail profissional","Endereço comercial","Full Name","Job Title / Role","Phone Numbers","Profissão","Razão social","Telefone profissional","E-mail profissional","Full Name","Job Title / Role","Telefone profissional","Business Unit / Division","CNPJ","E-mail profissional","Endereço comercial","Informações Societárias","Job Title / Role","Phone Numbers","Profissão","Razão social","Telefone profissional"        ],  -     "Terceiros": ["Profissão","Date of Birth","Full Name","Home Address","Marital Status","Nationality","Phone Numbers","CPF","Full Name","Vídeo","Voice Recognition","Vídeo","Voice Recognition","Bank Account Number","CNH","CNPJ","Company / Entity","Comprovante de Endereço","Contact Details","CPF","Date of Birth","E-mail profissional","Endereço comercial","Filiação a sindicato","Full Name","Gênero" ] } ]

The example below should remove the duplicates

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [\n    {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n        {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element2'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Parlamentares',\n        \"Data Element Name\": 'element1'\n      }    \n    }\n]"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        490,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "\nconst types = {};\n\nfor (const item of items) {\n  if (types[item.json[\"Data Subject Type Name\"]] === undefined) {\n      types[item.json[\"Data Subject Type Name\"]] = [];\n      types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n  } else {\n    if (!types[item.json[\"Data Subject Type Name\"]].includes(item.json['Data Element Name'])) {\n        types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n    }\n  }\n}\n\nreturn [{ json: types }]"
      },
      "name": "Function1",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        730,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Function1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Did it work?

1 Like

It works! Just tested it. Fantastic. Thx so much!!

1 Like

Ahead in my workflow I am using a Merge By key node, and just realized I need a key to use the results provided…

In that case, I think we need to structure it adding a fixed key name, right?

Something like:

{
    "jsonKeyName": "Customers",
    "anotherJsonKey": [
        "Razao social", "Phone Numbers",
    ]
}
{
    "jsonKeyName": "Employees",
    "anotherJsonKey": [
        "E-mail-profissional",
    ]
}

Appreciate your input again, and sorry I didnt catch this before (Merge By key requirement).

Check the example below:

{
  "nodes": [
    {
      "parameters": {
        "functionCode": "return [\n    {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n        {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element2'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Parlamentares',\n        \"Data Element Name\": 'element1'\n      }    \n    }\n]"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        510,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "\nconst types = {};\n\nconst results = [];\n\nfor (const item of items) {\n  if (types[item.json[\"Data Subject Type Name\"]] === undefined) {\n      types[item.json[\"Data Subject Type Name\"]] = [];\n      types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n  } else {\n    if (!types[item.json[\"Data Subject Type Name\"]].includes(item.json['Data Element Name'])) {\n        types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n    }\n  }\n}\n\n  for (let key of Object.keys(types)) {\n    let type = {};\n    type['key'] = key\n    type['data'] = types[key]\n    results.push(type)\n  }\n\nreturn [\n    {\n      json: results\n    }\n]"
      },
      "name": "Function1",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        750,
        300
      ]
    }
  ],
  "connections": {
    "Function": {
      "main": [
        [
          {
            "node": "Function1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Please, is it possible to get rid of the 1st level of [ ] ?

My Merge node is not detecting the key and I wonder if it is because of this extra [ ] in the JSON. Note it shows Results: 1

Thx again!

what are you doing after exactly? Because of that depend on how the data should be returned.

I’m trying to merge results from 2 different sources, Merge by Key as follows.

The left screenshot is a result of an HTTP Request API, and the right screenshot if the Function you helped me.

Thx

That should do it.

   {
      "nodes": [
        {
          "parameters": {},
          "name": "Start",
          "type": "n8n-nodes-base.start",
          "typeVersion": 1,
          "position": [
            250,
            300
          ]
        },
        {
          "parameters": {
            "functionCode": "return [\n    {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n        {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element1'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Customers',\n        \"Data Element Name\": 'element2'\n      }    \n    },\n            {\n      json: {\n        \"Data Subject Type Name\": 'Parlamentares',\n        \"Data Element Name\": 'element1'\n      }    \n    }\n]"
          },
          "name": "Function",
          "type": "n8n-nodes-base.function",
          "typeVersion": 1,
          "position": [
            500,
            300
          ]
        },
        {
          "parameters": {
            "functionCode": "\nconst types = {};\n\nconst results = [];\n\nfor (const item of items) {\n  if (types[item.json[\"Data Subject Type Name\"]] === undefined) {\n      types[item.json[\"Data Subject Type Name\"]] = [];\n      types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n  } else {\n    if (!types[item.json[\"Data Subject Type Name\"]].includes(item.json['Data Element Name'])) {\n        types[item.json[\"Data Subject Type Name\"]].push(item.json['Data Element Name'])\n    }\n  }\n}\n\n  for (let key of Object.keys(types)) {\n    let type = {};\n    type['key'] = key\n    type['data'] = types[key]\n    results.push({ json: type })\n  }\n\nreturn results"
          },
          "name": "Function1",
          "type": "n8n-nodes-base.function",
          "typeVersion": 1,
          "position": [
            740,
            300
          ]
        }
      ],
      "connections": {
        "Start": {
          "main": [
            [
              {
                "node": "Function",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Function": {
          "main": [
            [
              {
                "node": "Function1",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      }
    }
1 Like

Working perfectly. Your help is really appreciated. Thx a lot

1 Like