Trouble understanding slack and split into batches

Hello, I am trying to weekly have n8n go to google drive, and check two folders for any folders that have been added in the last week, and if so post on slack. My trouble stems from the fact that I am able to call the folder information, but since it is split into batches, I am unable to create a single summary slack post. How can I merge the outputs from the folders into a single set node in JSON format? I can output each individual folder as an item but I’m trying to merge those items back again into a json document. Any help is appreciated. Thanks!

{
  "nodes": [
    {
      "parameters": {
        "attachments": [],
        "otherOptions": {}
      },
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 1,
      "position": [
        1350,
        960
      ],
      "credentials": {
        "slackApi": "n8n Bot"
      },
      "disabled": true
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyWeek",
              "hour": 13
            }
          ]
        }
      },
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        -80,
        579
      ]
    },
    {
      "parameters": {
        "functionCode": "var curr = new Date;\nvar first = (curr.getDate() - curr.getDay()) +1;\nvar last = first + 4;\n\nvar firstday = new Date(curr.setDate(first));\nvar lastday = new Date(curr.setDate(last));\n\nbeginning_week = new Date(firstday.setHours(0,0,0,0));\nending_week = new Date(lastday.setHours(23,59,59,99));\n\nitems[0].json.from = beginning_week.toISOString();\nitems[0].json.to = ending_week.toISOString();\n\nreturn items;"
      },
      "name": "Start and end of week1",
      "type": "n8n-nodes-base.function",
      "position": [
        100,
        579
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "folder.scoped",
              "value": "1gaswxsAZsquyG_IA9JL0ChBPZtLNCGaT"
            },
            {
              "name": "folder.unscoped",
              "value": "1B46TbHO-MkCCV1_nGoeuDouFjWkXgzk3"
            }
          ]
        },
        "options": {}
      },
      "name": "Set PB Folder",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        280,
        579
      ]
    },
    {
      "parameters": {
        "operation": "list",
        "useQueryString": true,
        "queryString": "='{{$node[\"Build Slack Message PB Folder\"].json[\"folder\"][\"unscoped\"]}}' in parents",
        "options": {
          "fields": [
            "*"
          ]
        }
      },
      "name": "Get Unscoped PBs",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 1,
      "position": [
        440,
        780
      ],
      "credentials": {
        "googleApi": "TC Service Account"
      }
    },
    {
      "parameters": {
        "operation": "list",
        "useQueryString": true,
        "queryString": "='{{$node[\"Build Slack Message PB Folder\"].json[\"folder\"][\"scoped\"]}}' in parents",
        "options": {
          "fields": [
            "*"
          ]
        }
      },
      "name": "Get Scoped PBs",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 1,
      "position": [
        470,
        509
      ],
      "credentials": {
        "googleApi": "TC Service Account"
      }
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "pb.creator",
              "value": "="
            },
            {
              "name": "pb.createddate",
              "value": "={{$json[\"createdTime\"]}}"
            },
            {
              "name": "pb.name",
              "value": "={{$node[\"Split Scopes\"].json[\"name\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set scoped pb dict",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        840,
        349
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "pb.creator",
              "value": "={{$json[\"owners\"][0][\"displayName\"]}}"
            },
            {
              "name": "pb.createddate",
              "value": "={{$json[\"createdTime\"]}}"
            },
            {
              "name": "pb.name",
              "value": "={{$json[\"name\"]}}"
            },
            {
              "name": "pb.link",
              "value": "={{$json[\"webViewLink\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set unscoped pb dict",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        810,
        960
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "name": "Split Scopes",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        650,
        349
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "name": "SplitInBatches1",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        610,
        960
      ]
    },
    {
      "parameters": {
        "value": "={{$json[\"pb\"][\"createddate\"]}}",
        "dataPropertyName": "pb.createddatepretty",
        "toFormat": "MMMM DD YYYY",
        "options": {}
      },
      "name": "Date & Time",
      "type": "n8n-nodes-base.dateTime",
      "typeVersion": 1,
      "position": [
        980,
        960
      ]
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "slack.update",
              "value": "={\n\t\t\t\"type\": \"section\",\n\t\t\t\"text\": {\n\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\"text\": \"`{{$json[\"pb\"][\"createddatepretty\"]}}` *{{$json[\"pb\"][\"name\"]}}* Created by _ {{$json[\"pb\"][\"creator\"]}}_\"\n\t\t\t},\n\t\t\t\"accessory\": {\n\t\t\t\t\"type\": \"button\",\n\t\t\t\t\"text\": {\n\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\"text\": \"Open Folder\",\n\t\t\t\t\t\"url\": \"{{$json[\"pb\"][\"link\"]}}\",                    \n\t\t\t\t\t\"emoji\": true\n\t\t\t\t}\n\t\t\t}\n\t\t}"
            }
          ]
        },
        "options": {}
      },
      "name": "Build Slack Message",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        1170,
        960
      ]
    }
  ],
  "connections": {
    "Cron": {
      "main": [
        [
          {
            "node": "Start and end of week1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start and end of week1": {
      "main": [
        [
          {
            "node": "Set PB Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set PB Folder": {
      "main": [
        [
          {
            "node": "Get Scoped PBs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Unscoped PBs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Unscoped PBs": {
      "main": [
        [
          {
            "node": "SplitInBatches1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Scoped PBs": {
      "main": [
        [
          {
            "node": "Split Scopes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set unscoped pb dict": {
      "main": [
        [
          {
            "node": "Date & Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Scopes": {
      "main": [
        [
          {
            "node": "Get Scoped PBs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set scoped pb dict",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches1": {
      "main": [
        [
          {
            "node": "Get Unscoped PBs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set unscoped pb dict",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Date & Time": {
      "main": [
        [
          {
            "node": "Build Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Slack Message": {
      "main": [
        [
          {
            "node": "Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

This topic should help:

Yes I was trying to use that example in my logic but I was not able to understand it. I think the problem is that I don’t fully understand what needs to go into the function to make the different batches unite again. I tried using that example but it didn’t work so I’m assuming I need to tweak the function a bit to make it work?

In each loop (before going back to the SplitInBatches-Node) you need an IF-Node which exits the loop when there are no more items. That can be done with an expression like that:

={{$node["SplitInBatches"].context["noItemsLeft"]}}

You have to replace SplitInBatches with the name of your SplitInBatches-Node. So could also be SplitInBatches23

Here an example IF-Node:

{
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "number": [],
          "boolean": [
            {
              "value1": "={{$node[\"SplitInBatches\"].context[\"noItemsLeft\"]}}",
              "value2": true
            }
          ]
        }
      },
      "name": "IF no more batches",
      "type": "n8n-nodes-base.if",
      "position": [
        2362,
        665
      ],
      "typeVersion": 1
    }
  ],
  "connections": {}
}

The false-output of the IF-Node has to get connected to the SplitInBatches-Node and the true-output with a Function-Node. That Function-Node will collect the data of all Items. The code of that node would look like this:

const allData = []

let counter = 0;
do {
  try {
    const items = $items("Google Drive", 0, counter).map(item => item.json);
    allData.push.apply(allData, items);
  } catch (error) {
    return [{json: {allData}}];  
  }

  counter++;
} while(true);

There you have the replace Google Drive with the actual name of the node which contains the data you want to collect. So for example Get Scoped PBs looking at your workflow example.

If you do that you should have all the Items of all runs combined in the Function-Node.

This is incredible, thank you for your work! I’m going to apply this tonight.

It worked perfectly!!! Thank you so much for your help! I’m now trying to figure out how to format the slack post message to include all the sets that were generated by the split in batches, so any help there is appreciated but I’m sure I’ll figure it out! Thank you again!!

Glad to hear.

That can be done best via the Function-Node. In it there are multiple ways to do it and depends a lot on the input data and the message you want to send.

Here a very basic example:

let message = 'All the people:\n';

for (const item of items) {
  message += `- ${item.json.name}\n`;
}

return [
  {
    json: {
      message,
    }
  }
];

An example workflow for the context:

{
  "nodes": [
    {
      "parameters": {
        "functionCode": "return [\n  {\n    json: {\n      name: 'Jim',\n    }\n  },\n  {\n    json: {\n      name: 'Barb',\n    }\n  },\n  {\n    json: {\n      name: 'Jane',\n    }\n  }\n];"
      },
      "name": "Mock Data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "text": "={{$json[\"message\"]}}",
        "attachments": [],
        "otherOptions": {}
      },
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "let message = 'All the people:\\n';\n\nfor (const item of items) {\n  message += `- ${item.json.name}\\n`;\n}\n\nreturn [\n  {\n    json: {\n      message,\n    }\n  }\n];"
      },
      "name": "Create Message",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    }
  ],
  "connections": {
    "Mock Data": {
      "main": [
        [
          {
            "node": "Create Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Message": {
      "main": [
        [
          {
            "node": "Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

I seem to be having trouble calling these values, I seem to be close but I think the nested nature of the responses calls for a different call than (item.json.slackupdates.creator)

Screen Shot 2021-03-29 at 12.54.15 PM|690x224 Screen Shot 2021-03-29 at 2.20.16 PM