Skip to main content
Skip table of contents

Group by Path

LAST UPDATED: JUNE 18, 2025

The Merge task’s "groupBy": "Path" configuration enables merging by resolving one or more specified path expressions within upstream task outputs. For each successful path resolution, the entire execution lineage contributing to that match is merged into a separate result object.

Merge Condition Format

To apply this configuration, the merge condition must include at least the following two keys:

JSON
{
  "groupBy": "Path",
  "paths": [
    "$['<node1>'].<path>",
    "$['<node2>'].<path>",
    "$['<node3>'].<path>",
    "$['<nodeN>'].<path>"
  ]
}

Core Concepts

The examples below demonstrate how variations in task structure, path specification, and output availability influence merge.

Example 1 - Lineage Capture on Path Match

OBJECTIVE – Learn what data fields are returned when using groupBy: "Path" and specifying the return data path of a task node in a single linear execution stream.

  1. Build the following playbook:

    1670a36a-efa2-42bc-8e2a-6efb92183cbc.png
  2. Configure task A1 to return "A1", task A2 to return "A2", and task A3 to return "A3".

    Frame 25 (5)-20250603-213621.png
  3. Input the following merge condition:

    JSON
    {
        "groupBy": "Path",
        "paths": ["$['A1'].returnData"]
    }
    Frame 24 (4).png
  4. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  5. Observe the execution results for the Merge task in the Raw Data tab.

    Frame 26 (3)-20250603-214734.png
  6. Repeat steps 3-5 changing the paths key in the Condition parameter to reference different task nodes (i.e., A1, A2, and A3).

TAKEAWAYS

Regardless of which task is specified in the paths key, if a match is found, the entire execution lineage—DataSource, A1, A2, and A3 in this case—is consolidated into an object within the merge result.

Example 2 - Merge Task Output for Matched vs. Unmatched Paths

OBJECTIVE – Contrast the merge execution outputs for matched and unmatched paths.


  1. Build the following playbook:

  2. Configure task A1 to return "A1", task A2 to return "A2", and task A3 to return "A3".

    Frame 25 (5)-20250603-213621.png
  3. Configure task B1 to return "B1", task B2 to return "B2", and task B3 to return "B3".

    Frame 30 (1)-20250604-173643.png
  4. Input the following merge condition:

    JSON
    {
        "groupBy": "Path",
        "paths": ["$['B1'].returnData"]
    }
  5. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  6. Observe that two execution instances of the Merge task are present.

READER NOTE

The number of executions, indicated by the icon, reflects the count of completed tasks that provide input via connecting arrows.

  1. Observe the execution results for the Merge task in the Raw Data tab.

    Frame 31 (1)-20250604-175738.png
  2. Observe the execution results for the other instance.

    Frame 32 (1)-20250604-180243.png

TAKEAWAY

The Raw Data tab, containing the merge results, renders only for execution instances that match the Merge condition.

Example 3 - Merge Results for Playbooks with Common Ancestor Nodes and Parallel Branches

OBJECTIVE – Learn how the paths key affects merge results when parallel branches share a common ancestor node.


  1. Build the following playbook:

  2. Input the following merge condition:

    JSON
    {
        "groupBy": "Path",
        "paths": ["$['1'].returnData"]
    }
    Frame 33 (3)-20250604-191933.png
  3. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  4. Click on the icon within the Merge node.

    Frame 34 (3)-20250604-192948.png
  5. Observe the execution results for the Merge task in the Raw Data tab.
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "1": { ... },
        "2.2": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "1": { ... },
        "2.1": { ... },
        "3": { ... }
      }
    ]
  6. Stop the test, then repeat steps 2-5 using the paths key ["$['2.1'].returnData"] or ["$['3'].returnData"].
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "1": { ... },
        "2.1": { ... },
        "3": { ... }
      }
    ]
  7. Stop the test, then repeat steps 2-5 using the paths key ["$['2.2'].returnData"].
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "1": { ... },
        "2.2": { ... },
        "Merge": { ... }
      }
    ]

TAKEAWAYS

  • When the paths key matches a task that splits into parallel branches (i.e., 1), the merge result will include a lineage object for each of them.

  • When the paths key matches a task in one branch (e.g., 2.2), the merge result excludes sibling branch nodes (e.g., 2.1 → 3).

Example 4 - Grouping by Unwind Context vs. Return Values

OBJECTIVE – Compare grouping by an Unwind task's contextData path versus the returnData paths of its downstream tasks.


  1. Build the following playbook:

  2. Input the following JSON data for the Unwind A task:

    JSON
    [
      { "demoKey1": "value1", "demoKey2": "value2" },
      { "demoKey3": "value3", "demoKey4": "value4" },
      { "demoKey5": "value5", "demoKey6": "value6" }
    ]
    Frame 63 (1)-20250611-011703.png

  3. Configure task B1 to return the following:

    JSON
    [
      { "demoKey7": "value7", "demoKey8": "value8" },
      { "demoKey9": "value9", "demoKey10": "value10" },
      { "demoKey11": "value11", "demoKey12": "value12" }
    ]
  4. Input the following dynamic JSON Data parameter for the Unwind B task:

    JSON
    {{ $.PlaybookData.B1.returnData }}
    Frame 66-20250611-185740.png
  5. Configure task A2 to return "A2", task task B3 to return "B3", and task AB to return "AB".

    Frame 65-20250611-185007.png
  6. Select and configure a Delay system utility command task with a 5 second duration.

    Frame 39 (1)-20250605-000750.png
  7. Input the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": ["$.['Unwind A'].contextData"]
    }
    Frame 67-20250611-190215.png
  8. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  9. Click on the icon within the Merge node.

    Frame 41 (1)-20250605-002456.png
  10. Locate execution instances with the Raw Data tab visible, then review the execution result.
    MERGE RESULT 1

    JSON
    [
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]

    MERGE RESULT 2

    JSON
    [
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]

    MERGE RESULT 3

    JSON
    [
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]
  11. Stop the test, then repeat steps 8-10 using the paths key ["$.['A2'].returnData"].
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]
  12. Stop the test, then repeat steps 8-10 using the paths key ["$.['Unwind B'].contextData"].
    MERGE RESULT 1

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... }
      }
    ]

    MERGE RESULT 2

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]

    MERGE RESULT 3

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]
  13. Stop the test, then repeat steps 8-10 using the paths key ["$.['B3'].returnData"].
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... }
      }
    ]
  14. Stop the test, then repeat steps 8-10 using the paths key ["$.['AB'].returnData"].
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "Unwind A": { ... },
        "A2": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      },
      {
        "DataSource": { ... },
        "B1": { ... },
        "Unwind B": { ... },
        "B3": { ... },
        "Delay 5 Seconds": { ... },
        "AB": { ... },
        "Merge": { ... }
      }
    ]

TAKEAWAYS

  • Grouping by the contextData path of an Unwind task produces one merge result per deconstructed item.

    • Grouping by subsequent tasks' returnData, even when multiple execution instances exist, yields a single merge result.

Example 5 - Grouping Multiple Paths

OBJECTIVE – Demonstrate the use of multiple paths for the merge condition, and the impact of a missing path on the resulting merged output.


  1. Build the following playbook:

  2. Input the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
        "$.['A2.1'].returnData",
        "$.['B1'].returnData"
      ]
    }
    Frame 42-20250606-210158.png
  3. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  4. Click on the icon within the Merge node.

    Frame 43-20250606-213123.png
  5. Verify that two execution instances of the Merge task display a Raw Data tab containing an array.
    MERGE RESULT 1

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "Merge": { ... }
      }
    ]
    Frame 44-20250606-214238.png

    MERGE RESULT 2

    JSON
    [
      {
        "DataSource": { ... },
        "A1": { ... },
        "A2.1": { ... },
        "Merge": { ... }
      }
    ]
    Frame 45-20250606-214257.png
  6. Stop the test, then repeat steps 2-5 using the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
        "$.['A2.1'].returnData",
        "$.['B1'].contextData"
      ]
    }


    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "A1": { ... },
        "A2.1": { ... },
        "Merge": { ... }
      }
    ]

    Because task node B1 does not include a contextData path in its output, only one merge result is generated.

    Frame 46 (1)-20250606-221235.png
  7. Stop the test, then repeat steps 2-5 using the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
        "$.['B1'].returnData",
        "$.['B2.1'].returnData"
      ]
    }

    MERGE RESULT 1

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "B2.2": { ... }
      }
    ]

    MERGE RESULT 2

    JSON
    [
      {
        "DataSource": { ... },
        "B1": { ... },
        "B2.1": { ... },
        "Merge": { ... }
      }
    ]

TAKEAWAY

Each path specified in the merge condition that resolves to a value contributes an output array to a separate merge instance.

Example 6 - Number of Merge Results vs. Number of Downstream Executions

OBJECTIVE – Illustrate how the number of merge results reflects the number of downstream executions.


  1. Build the following playbook:

  2. Configure task D to return "D".

    Frame 69-20250611-234335.png
  3. Input the following merge condition:

    JSON
    { 
        "groupBy": "Path",
        "paths": ["$['D'].returnData"]
    }
    Frame 73-20250612-003847.png
  4. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  5. Note that the task positioned downstream of the Merge task executes a single time.

    Frame 70 (1)-20250611-235225.png

  1. Build the following playbook:

  2. Configure task C to return "C".

    Frame 76-20250612-004900.png
  3. Input the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
           "$['Unwind A'].contextData",
           "$['Unwind B'].contextData"
      ]
    }
    Frame 75-20250612-004517.png
  4. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  5. Note that the task positioned downstream of the Merge task executes six times.

  6. Input the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
           "$['Unwind A'].contextData",
           "$['Unwind B'].contextData",
           "$['C'].returnData"
      ]
    }
    Frame 74-20250612-004101.png
  7. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  8. Note that the task positioned downstream of the Merge task executes seven times.

    image 2.png

TAKEAWAY

The number of downstream executions, following the Merge task, has a 1:1 correspondence with the number of Merge task executions that have produced a result.


FAQ

How can users specify a merge condition for deeply nested elements in JSON?

OBJECTIVE – Learn how to configure the merge condition to point to a nested path.

  1. Build the following playbook:

  2. Configure task A to return the following:

    JSON
    [
      {
        "layer1": {
          "layer2": [
            {
              "layer3": {
                "layer4": {
                  "layer5": {
                    "values": [
                      { "id": 1, "data": ["1", "11", "111"] },
                      { "id": 2, "data": ["2"] },
                      { "id": 3, "data": ["3", "33", "333"] }
                    ]
                  }
                }
              }
            },
            {
              "layer3": {
                "layer4": {
                  "layer5": {
                    "values": [
                      { "id": 4, "data": ["4", "44", "444"] },
                      { "id": 5, "data": ["5", "55", "555"] },
                      { "id": 6, "data": ["6", "66", "666"] }
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    ]

TARGET – Task A: Check for the presence of a second element in the "data" array within the second object of a nested "values" array.

The merge condition's paths key supports the recursive descent operator (..).

  1. Input the merge condition:

    JSON
    {
      "groupBy": "Path",
      "taskName": "A",
      "paths": [ "$['A']..values[1].data[1]" ]
    }
  2. Test run the playbook.

    Frame 1 (31)-20250602-235821.png

  3. Click on the icon within the Merge node.

    Frame 110-20250618-004703.png
  4. Observe the merge result in the Raw Data tab.
    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "A": { ... },
        "Merge": { ... }
      }
    ]

READER NOTE *

The second "layer2" element includes a nested "values" array whose second object contains a "data" array with a second element.

Frame 113-20250618-214713.png

TARGET – Task A: Check for the presence of a second element in the "data" array of all nested "value" objects where the id equals 5.

  1. Repeat steps 3-6 with using the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
        "$['A']..values[?(@.id==5)].data[1]"
      ]
    }

    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "A": { ... },
        "Merge": { ... }
      }
    ]

MERGE CONDITION EXPLANATION *

The filter ?(@.id==5) selects an object within "values" arrays where the "id" specifically equals 5. The subsequent .data[1] accesses the second element of the "data" array within that same object.


TARGET – Task A: Check for the presence of a second element in any "data" array.

  1. Repeat steps 3-6 with using the following merge condition:

    JSON
    {
      "groupBy": "Path",
      "paths": [
        "$['A']..data[1]"
      ]
    }

    MERGE RESULT

    JSON
    [
      {
        "DataSource": { ... },
        "A": { ... },
        "Merge": { ... }
      }
    ]

MERGE CONDITION EXPLANATION *

This merge condition checks for the presence of a second element in any "data" array located at any depth.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.