---
schema_version: "1"
id: 3201049339af4b0e6a91f486f1412cf70dd83181c64dd6128b87191e9e4888ab
title: "Macros Use Case: Recursive Operations"
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/analytics/atf/guides/atf-rules-macro-use-case-recursive-ops.md
canonical_url: https://developer.salesforce.com/docs/analytics/app-template-framework/guide/atf-rules-macro-use-case-recursive-ops.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 54fc3cc6565adec1b925288053437d62174c126bdab7ae4886225b0c5cdeb186
products:
  - App Template Framework
  - analytics
---
# Macros Use Case: Recursive Operations

Here’s an example of a macro that deletes a `sfdcDigest` node. It also deletes the digest node and all other nodes that depend on that node.

This macro deletes the specified node and dynamically queries the JSON document to delete each dependency of those nodes.

Consider the simplified JSON below. To delete `node3` and its dependencies, the result should delete: `node3`, `node4`, `node5` (depends on `node4`), `node6` (depends on `node5`), `node7`, `node8`, and `node9`.

## Example

Example JSON

```json
{
    "node1": { },
    "node2": {
        "dependsOn": "node1"
    },
    "node3": {
        "dependsOn": "node2"
    },
    "node4": {
        "dependsOn": "node3"
    },
    "node5": {
        "dependsOn": "node4"
    },
    "node6": {
        "dependsOn": "node5"
    },
    "node7": {
        "dependsOn": "node3"
    },
    "node8": {
        "dependsOn": "node3"
    },
    "node9": {
        "dependsOn": "node3"
    }
}
```

## Example Without Macro

Without using a macro (and associated enhancements), nodes would have to be deleted individually.

```json
{
    "rules": [
        {
            "name": "Delete node3 and dependencies",
            "actions": [
               {
                   "action": "delete",
                   "path": "$.node3"
               },
               {
                   "action": "delete",
                   "path": "$.node4"
               },
              {
                   "action": "delete",
                   "path": "$.node5"
               },
              {
                   "action": "delete",
                   "path": "$.node6"
               },
               {
                   "action": "delete",
                   "path": "$.node7"
               },
               {
                   "action": "delete",
                   "path": "$.node8"
               },
               {
                   "action": "delete",
                   "path": "$.node9"
               }
           ]
      }
  ]
}
```

This code is rigid and difficult to maintain because the rules need to be modified as node dependencies are added and removed from the JSON payload.

## Example with a Recursive Macro

```json
{
    "namespace": "macroRecursion",
    "definitions": [
        {
            "name": "deleteNodeAndDependencies",
            "description": "Delete a node and its dependencies.  Returns an array of json paths of all the nodes that were deleted.",
            "parameters": [
                "nodeName"
            ],
            "actions": [
                {
                  "action": "eval", 
                  "key": "fullNodePath",
                  "value": "$.${p.nodeName}" 
                },
                {
                  "action": "eval", 
                  "key": "dependencies",  
                  "value": "${macroRecursion:getDependents(p.nodeName)}"
                },
                {
                  "action": "eval",
                  "value": "${array:forEach(Rules.Eval.dependencies, '${macroRecursion:deleteNodeAndDependencies(macroRecursion:deleteSingleNodeByFullJsonPath(var))}')}"
                },
                {
                   "action": "eval",
                   "value": "${macroRecursion:deleteSingleNodeByFullJsonPath(Rules.Eval.fullNodePath)}"
                }
            ]
        },
        {
            "name": "deleteSingleNodeByFullJsonPath",
            "description": "Deletes a node by full json path.",
            "parameters": [
                "fullJsonPath"
            ],
            "actions": [
              {
                "action": "eval",
                "key": "pathSegments",
                "value": "${string:match(p.fullJsonPath,'\\\\[\\'(.*?)\\'\\\\]')}"
              },
              { 
                "action": "delete",  
                "path": "${p.fullJsonPath}"
              }
            ],
            "returns": "${array:last(Rules.Eval.pathSegments)}"
        },
        {
            "name": "getDependents",
            "description": "Returns the full json path to search results",
            "parameters": [
                "nodeName"
            ],
            "actions": [
              { 
                "action": "eval", 
                "key": "searchString", 
                "value": "$.*[?(@.dependsOn=='${p.nodeName}')]"
              },
              { 
                "action": "eval", 
                "key": "paths", 
                "value": "${json:searchPaths(Rules.Eval.searchString)}"
              }
            ],
            "returns": "${Rules.Eval.paths}"
        }
    ]
 }
```

Then, use a rule to call the macro:

```json
{
    "rules": [
        {
            "name": "Recursively delete node3 and dependencies",
            "actions": [
                {
                  "action": "eval", 
                  "value": "${macroRecursion:deleteNodeAndDependencies('node3')}"
                }
            ]
        }
    ]
}
```

[Back to Macros in Rules](https://developer.salesforce.com/docs/analytics/app-template-framework/guide/atf-rules-macros.md)