Passing function node output as one item

Hey there,

I have a graphql node that I’m using to do an insert. But the service I’m using has capacity limits (60 ops per minute) and I want to insert ~ 500 nested objects.

What I’ve tried is this in a function node to aggregate the objects that I want to pass to the gql node as a single list:

gqlObjects = items.map(i => {
  var item = i.json
  return { blah = item['foo'] }
})
return [{json: gqlObjects}]

But when I try this:

mutation InsertEmployment {
  insert_employment(objects: {{ $json }}) {
    returning {
      nested
      id
      stuff {
        here
      }
    }
  }
}

It isn’t building a valid query. Is there any way I can pass $json as an array?

Hey @commandodev! :wave:

Welcome to the n8n community! :slightly_smiling_face:

I have created an example workflow that might help. The Function node in the example workflow is to create the mock data. In the GraphQL node I am first converting the array into a string using the JSON.stringify() method. Next I am replacing the "name" with name (removing the quotes), since that is the value of the key and in GraphQL we don’t use quotes for the key. I hope this helps.

{
  "nodes": [
    {
      "parameters": {
        "endpoint": "https://api.spacex.land/graphql/",
        "requestFormat": "json",
        "query": "=mutation {\n  insert_users(objects:{{JSON.stringify($node[\"Function\"].json).replace(/\"name\"/g,'name')}} ) {\n    returning {\n      name\n    }\n  }\n}",
        "responseFormat": "string"
      },
      "name": "GraphQL",
      "type": "n8n-nodes-base.graphql",
      "typeVersion": 1,
      "position": [
        800,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{json:[{name: \"test\"}, {name: \"test1\"}]}];"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        550,
        300
      ]
    }
  ],
  "connections": {
    "Function": {
      "main": [
        [
          {
            "node": "GraphQL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Thanks @harshil1712! Is there any reason you’re referring to the Function node like this $node[\"Function\"].json instead of just using $json?

I’ll give this a try!

Actually another thought @harshil1712 - is there a string template library I can use in n8n nodes? I think it would make sense to construct the payload in the function node…

@commandodev I am referring the Function node as in the example as that is more of a convenient way. If you have multiple data sources then it would create an issue. Specifying which node I want to use the data from makes it less complicated.

Currently, we don’t have a string template library bundled in n8n. You can read more about in this thread

Ah that’s a shame… I have a lot of keys I’m going to have to regex like this. I’ll have to see if I can build a regex for all valid keys…

As a temporary workaround is the same already possible in the Function-Node. If you start n8n with the following environment variable to make sure that handlebars can be used:

export NODE_FUNCTION_ALLOW_EXTERNAL=handlebars

Then you can do the following:

{
  "nodes": [
    {
      "parameters": {
        "functionCode": "return [\n  {\n    json:   {\n      name: 'Frank',\n      hometown: 'Berlin',\n    },\n  },\n  {\n    json: {\n      name: 'John',\n      hometown: 'New York',\n    }, \n  }, \n];"
      },
      "name": "Mock Data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "const Handlebars = require('handlebars');\n\nlet source = \"<p>Hello, my name is {{name}}. I am from {{hometown}}</p>\";\nlet template = Handlebars.compile(source);\n\nitems.forEach(item => {\n  item.json.myText = template(item.json);\n})\n\nreturn items;"
      },
      "name": "Function-Template",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    }
  ],
  "connections": {
    "Mock Data": {
      "main": [
        [
          {
            "node": "Function-Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
1 Like

Ah nice, I would definitely rather use handlebars next time!

In the end I came up with: .replace(/"([a-z0-9_]*)":/g, "\$1:") :slight_smile: