Using a Splitinbatches inside another Splitinbatches as a terms Filter

Hello. I’m getting a list of Twitter spaces rooms and comparing the title against a list in google sheets of derogatory terms. I need to run a splitinbatches with a larger splitinbatches that separately checks the title of each item again a list of non approved terms in google sheets. If the item title contains one of the 10 terms, then an IF will route to the next item in the larger batch. But if there are no matches then the workflow would continue as normal processing the current item.


{
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "boolean": [],
          "string": [
            {
              "value1": "={{$node[\"Twitter3\"].json[\"data\"][\"title\"].toLowerCase()}}",
              "operation": "contains",
              "value2": "={{$node[\"Badword-items\"].json[\"term\"]}}"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "IF-Explicit Filter",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1300,
        740
      ],
      "alwaysOutputData": false,
      "notesInFlow": true,
      "retryOnFail": false,
      "notes": "Filter\n\nTurned off \"Always Output Data\" and \"Retry on Fail\" as they shouldn't be needed at this point."
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "sheetId": "1fu4JxYNdQ8CLvPXbahTX-KJ-G9Xxo8PMyMqpyU8G6m0",
        "options": {}
      },
      "name": "Google Sheets2",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 1,
      "position": [
        780,
        740
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "20",
          "name": "Google Sheets account 2"
        }
      }
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {
          "reset": true
        }
      },
      "name": "Badwords-batch",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        940,
        740
      ]
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "term",
              "value": "={{$node[\"Badwords-batch\"].json[\"Word\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Badword-items",
      "type": "n8n-nodes-base.set",
      "position": [
        1100,
        740
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "IF-Explicit Filter": {
      "main": [
        null,
        [
          {
            "node": "Google Sheets2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets2": {
      "main": [
        [
          {
            "node": "Badwords-batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Badwords-batch": {
      "main": [
        [
          {
            "node": "Badword-items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Badword-items": {
      "main": [
        [
          {
            "node": "IF-Explicit Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

I’ve made some progress but my explicit words IF won’t trigger as true when there is a match and if there more than 2 titles then entire flows ends after 2 the second title.

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        0,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": true,
              "value2": "={{$node[\"BatchofTitles\"].context[\"noItemsLeft\"]}}"
            }
          ]
        }
      },
      "name": "IF3",
      "type": "n8n-nodes-base.if",
      "position": [
        2460,
        700
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [],
          "string": [
            {
              "value1": "={{$node[\"BatchofTitles\"].json[\"title\"].toLowerCase()}}",
              "operation": "contains",
              "value2": "={{$node[\"BatchofTerms\"].json[\"Word\"]}}"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "IF-Explicit Filter1",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1640,
        580
      ],
      "alwaysOutputData": false,
      "notesInFlow": true,
      "retryOnFail": false,
      "notes": "Filter\n\nTurned off \"Always Output Data\" and \"Retry on Fail\" as they shouldn't be needed at this point."
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "sheetId": "1fu4JxYNdQ8CLvPXbahTX-KJ-G9Xxo8PMyMqpyU8G6m0",
        "options": {}
      },
      "name": "BadTerms",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 1,
      "position": [
        960,
        580
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "20",
          "name": "Google Sheets account 2"
        }
      }
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {
          "reset": false
        }
      },
      "name": "BatchofTitles",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        460,
        580
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "sheetId": "1E7xR4A5a1sqzG-Z4XgIjgeZ5FXk7SmtzulA7gDNzmgc",
        "range": "A:A",
        "options": {}
      },
      "name": "Titles",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 1,
      "position": [
        220,
        580
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "20",
          "name": "Google Sheets account 2"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": true,
              "value2": "={{$node[\"BatchofTerms\"].context[\"noItemsLeft\"]}}"
            }
          ]
        }
      },
      "name": "IF2",
      "type": "n8n-nodes-base.if",
      "position": [
        2060,
        620
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "amount": 5,
        "unit": "seconds"
      },
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        2380,
        500
      ],
      "webhookId": "a6a0fa4a-87d8-4e57-b849-1b6bf75c4f4c"
    },
    {
      "parameters": {
        "amount": 2,
        "unit": "seconds"
      },
      "name": "Wait2",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        1880,
        520
      ],
      "webhookId": "72a8e7bd-6610-45e1-bccb-6683abd46bb4",
      "disabled": true
    },
    {
      "parameters": {
        "amount": 2,
        "unit": "seconds"
      },
      "name": "Wait3",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        2220,
        880
      ],
      "webhookId": "4369cee0-e296-4d22-9261-a1d59c802a4f"
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            {
              "name": "id",
              "value": "={{$node[\"BadTerms\"].json[\"Word\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "position": [
        1400,
        580
      ],
      "typeVersion": 1,
      "disabled": true
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "title",
              "value": "={{$node[\"BatchofTitles\"].json[\"title\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set2",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        740,
        580
      ],
      "disabled": true
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "name": "BatchofTerms",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        1180,
        580
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Titles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF3": {
      "main": [
        null,
        [
          {
            "node": "BatchofTitles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF-Explicit Filter1": {
      "main": [
        [
          {
            "node": "BatchofTitles",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BadTerms": {
      "main": [
        [
          {
            "node": "BatchofTerms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BatchofTitles": {
      "main": [
        [
          {
            "node": "Set2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Titles": {
      "main": [
        [
          {
            "node": "BatchofTitles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF2": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "IF3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait2": {
      "main": [
        [
          {
            "node": "IF2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait3": {
      "main": [
        [
          {
            "node": "BadTerms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "IF-Explicit Filter1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set2": {
      "main": [
        [
          {
            "node": "BadTerms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BatchofTerms": {
      "main": [
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

I’ve reintegrated the word filter splitinbatch into my main workflow. But I don’t understand, for some reason it only runs twice even though there are 112 items to check.

It seems to stop just before sending the terms list to the BatchofTerm splitinbatch for the 3rd time.

image

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "batchSize": "={{1}}",
        "options": {
          "reset": false
        }
      },
      "name": "SplitInBatches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        1540,
        120
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [],
          "string": [
            {
              "value1": "={{$node[\"Google Sheets\"].json[\"spaces_url\"]}}",
              "operation": "isEmpty"
            }
          ]
        }
      },
      "name": "IF3",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1740,
        1080
      ],
      "alwaysOutputData": false,
      "notesInFlow": true,
      "retryOnFail": false,
      "notes": "Filter\n\nTurned off \"Always Output Data\" and \"Retry on Fail\" as they shouldn't be needed at this point."
    },
    {
      "parameters": {
        "amount": 15,
        "unit": "minutes"
      },
      "name": "Wait6",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        880,
        900
      ],
      "webhookId": "c8427116-f5cd-4d8d-b5a8-48513dc13398"
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Twitter3\"].json[\"error\"]}}",
              "value2": "The service is receiving too many requests from you! Perhaps take a break?"
            }
          ]
        }
      },
      "name": "IF6",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        580,
        920
      ]
    },
    {
      "parameters": {
        "amount": 15,
        "unit": "minutes"
      },
      "name": "Wait9",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        1140,
        80
      ],
      "webhookId": "c8427116-f5cd-4d8d-b5a8-48513dc13398"
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"Twitter\"].json[\"error\"]}}",
              "value2": "The service is receiving too many requests from you! Perhaps take a break?"
            }
          ]
        }
      },
      "name": "IF7",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        800,
        120
      ]
    },
    {
      "parameters": {
        "resource": "spaces",
        "operation": "search_spaces_keyword",
        "query": "black",
        "additionalFields": {
          "expansions": "creator_id",
          "space_fields": "host_ids,created_at,creator_id,id,lang,invited_user_ids,participant_count,speaker_ids,started_at,ended_at,topic_ids,state,title,updated_at,scheduled_start,is_ticketed",
          "user_fields": "public_metrics,profile_image_url"
        }
      },
      "name": "Twitter2",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        340,
        60
      ],
      "credentials": {
        "twitterBearerToken": {
          "id": "17",
          "name": "Twitter V2 Bearer Token account"
        }
      }
    },
    {
      "parameters": {
        "values": {
          "string": [
            {
              "name": "time",
              "value": "={{$node[\"Parsed-TwitterSpacebyKeyword\"].json[\"created_at\"]}} {{$node[\"Parsed-TwitterSpacebyKeyword\"].json[\"started_at\"]}}"
            }
          ]
        },
        "options": {}
      },
      "name": "Set",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        1020,
        220
      ]
    },
    {
      "parameters": {
        "functionCode": "let response = []\nfor (d of items[0].json.data) {\n  let user = {}\n  for (e of items[0].json.includes.users){\n    if(e[\"id\"] == d[\"creator_id\"]){\n      user = e\n      break;\n    }\n  }\n  d.user = user\n  response.push({ json : d})\n}\nreturn response\n"
      },
      "name": "Parsed-TwitterSpacebyKeyword",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        640,
        60
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {
          "reset": false
        }
      },
      "name": "BatchofTerms",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        580,
        640
      ],
      "alwaysOutputData": false,
      "retryOnFail": false
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "sheetId": "1fkrkbGfF-pqeceXr6H8xNEQD2-0JaYZpH3ZcDYaAcF4",
        "range": "A:A",
        "options": {}
      },
      "name": "Terms",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 1,
      "position": [
        60,
        620
      ],
      "alwaysOutputData": true,
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "20",
          "name": "Google Sheets account 2"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [],
          "string": [
            {
              "value1": "={{$node[\"SplitInBatches\"].json[\"title\"]}}",
              "operation": "contains",
              "value2": "={{$node[\"BatchofTerms\"].json[\"Word\"]}}"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "IF-Explicit Filter2",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        880,
        640
      ],
      "alwaysOutputData": false,
      "notesInFlow": true,
      "retryOnFail": false,
      "notes": "Filter\n\nTurned off \"Always Output Data\" and \"Retry on Fail\" as they shouldn't be needed at this point."
    },
    {
      "parameters": {
        "unit": "seconds"
      },
      "name": "Wait1",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [
        300,
        640
      ],
      "webhookId": "ce919af3-cfe7-4b52-a7ca-e8a2ca318e07"
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": true,
              "value2": "={{$node[\"BatchofTerms\"].context[\"noItemsLeft\"]}}"
            }
          ]
        }
      },
      "name": "IF8",
      "type": "n8n-nodes-base.if",
      "position": [
        1220,
        660
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": true,
              "value2": "={{$node[\"BatchofTerms\"].context[\"noItemsLeft\"]}}"
            }
          ]
        }
      },
      "name": "IF9",
      "type": "n8n-nodes-base.if",
      "position": [
        1200,
        480
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Twitter2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches": {
      "main": [
        [
          {
            "node": "Terms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF3": {
      "main": [
        null,
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF6": {
      "main": [
        [
          {
            "node": "Wait6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF7": {
      "main": [
        [
          {
            "node": "Wait9",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Twitter2": {
      "main": [
        [
          {
            "node": "Parsed-TwitterSpacebyKeyword",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsed-TwitterSpacebyKeyword": {
      "main": [
        [
          {
            "node": "IF7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BatchofTerms": {
      "main": [
        [
          {
            "node": "IF-Explicit Filter2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Terms": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF-Explicit Filter2": {
      "main": [
        [
          {
            "node": "IF9",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "BatchofTerms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF8": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "BatchofTerms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF9": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

That’s quite a workflow :grinning:. Unfortunately, I am not sure I fully understand what is expected here. Nesting multiple Split in Batches definitely is nothing I would have done before. Would you be able to provide an example workflow using mock data showing the problem rather than relying on resources others can’t access (like a specific Twitter account or Google Sheet)?

From looking at the whole thing I wonder if, instead of using nested Split in Batches nodes, you could just fetch the list and perform a bunch of comparisons using the Merge nodes’ Remove Key Matches operation (if you’re looking for exact matches).

Alternatively you could convert your prohibited terms into an array, for example using the Item Lists nodes’ Aggregate Items operation and then use .some() to verify whether your text includes any of the forbidden terms. Here’s an example showing the idea (where I am setting a dummy array of prohibited items and fetch Tweets using a search for n8n, then use a Function Item node to add a property contains_prohibited_term to each item which can be used in IF nodes afterwards):

Example Workflow
{
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$json[\"contains_prohibited_term\"]}}",
              "value2": true
            }
          ]
        }
      },
      "name": "Contains Prohibited Term?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "operation": "search",
        "searchText": "n8n",
        "limit": 100,
        "additionalFields": {
          "resultType": "recent"
        }
      },
      "name": "Get Example Tweets",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        680,
        300
      ],
      "executeOnce": true,
      "credentials": {
        "twitterOAuth1Api": {
          "id": "15",
          "name": "@MutedJam"
        }
      }
    },
    {
      "parameters": {
        "functionCode": "return [{\n  json: {\n    prohibited_terms: [\"code\", \"boring\"]\n  }\n}]"
      },
      "name": "Set Example Prohibited List",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "const prohibited_terms = $items(\"Set Example Prohibited List\")[0].json.prohibited_terms;\nitem.contains_prohibited_term = prohibited_terms.some(e => item.text.includes(e));\nreturn item;"
      },
      "name": "Filter Prohibited Terms",
      "type": "n8n-nodes-base.functionItem",
      "typeVersion": 1,
      "position": [
        900,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$json[\"contains_prohibited_term\"]}}",
              "value2": true
            }
          ]
        }
      },
      "name": "Contains Prohibited Term?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1120,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set Example Prohibited List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Example Tweets": {
      "main": [
        [
          {
            "node": "Filter Prohibited Terms",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Example Prohibited List": {
      "main": [
        [
          {
            "node": "Get Example Tweets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Prohibited Terms": {
      "main": [
        [
          {
            "node": "Contains Prohibited Term?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

You can obviously perform such filtering multiple times for different sets of prohibited terms.

1 Like