> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/xql-command-reference-guide/readme/functions/hierarchy_match.md).

# hierarchy\_match

Use the `hierarchy_match()` function to determine whether an asset belongs to a specified node in the organizational (org) asset hierarchy. You can match against the hierarchy path (the ordered list of container names from the org root down to a specific node), a specific hierarchy node ID (`id_path`), or both. Calling the function with no arguments matches every asset (equivalent to `*`).

The function is only available when the org asset hierarchy is enabled for your tenant, and it operates on the asset hierarchy fields `xdm.asset.hierarchy.path` (the chain of container names joined by `/`) and `xdm.asset.hierarchy.id_path` (the ID of the deepest node in that path). It is intended for asset datasets (for example, `asset_inventory`) and is not supported inside correlation rules.

## Syntax

```sql
hierarchy_match(<path_segments>, <id_path>)
```

## Parameters

| Name            | Type   | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| --------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path_segments` | array  | No       | An ordered list of the container names from the org root down to the target node (for example, `["Org", "ou1", "ou2"]`). Segments are joined with `/` and matched as a path prefix, so the node and all of its descendants match. The path contains only container levels (organization, OUs, management groups, folders) — not the leaf account/project/subscription. If omitted (or an empty array), no path restriction is applied and all paths match. As a shorthand, passing a single string value is treated as the `id_path` argument. |
| `id_path`       | string | No       | The resource ID of a specific hierarchy node — the ID of the deepest container in the path (for example, an OU ID, management-group ID, or folder ID). Use it to unambiguously target a node even when names are duplicated. When provided, it must match the asset's `id_path`. If omitted, no ID restriction is applied.                                                                                                                                                                                                                     |

## Returns

**Type**: boolean

**Description**: The `hierarchy_match()` function returns `true` if the asset belongs to the specified org hierarchy node (satisfying both the path and ID conditions that were supplied), and `false` otherwise.

## Usage notes

* **Path vs. id\_path**: The `path` and `id_path` describe the same container node from two angles: `path` is the chain of container names, and `id_path` is the ID of the deepest node in that chain. Neither includes the account/project/subscription.
* **Disambiguating duplicate names**: Use `id_path` when container names are ambiguous. For example, if two different OUs are both named `Production`, matching on the path name alone is ambiguous — supplying the OU's `id_path` pins the match to exactly the OU you mean.
* **Combinable, optional parameters**: Both parameters are optional and can be combined:
  * `hierarchy_match()` — matches all assets (no restriction).
  * `hierarchy_match(arraycreate("Org", "ou1"))` — path-only match (the node and all its descendants).
  * `hierarchy_match(null, "ou-a1b2-prod01")` — ID-only match (match the node with this exact ID, on any path).
  * `hierarchy_match("ou-a1b2-prod01")` — shorthand for an ID-only match.
  * `hierarchy_match(arraycreate("Org", "ou1"), "ou-a1b2-prod01")` — matches only when both the path prefix and the ID condition are satisfied.
* **Prefix, case-sensitive, literal matching**: The path match is a prefix match: it matches the exact path as well as any child path beneath it. It is case-sensitive and matches literal characters (wildcard characters such as `%` and `_` in path segments are treated literally, not as wildcards).
* **Ambiguous scalar + ID is rejected**: Passing a single scalar/string value together with an explicit `id_path` is ambiguous and is rejected with a validation error. Use an array for the first argument whenever you also supply an ID.
* **Negation**: To negate a match (find assets that do not belong to a node), compare the result to `false` (for example, `hierarchy_match(...) = false`) or use `!= true`.
* **Typical use**: This function is typically used within the `filter` stage to scope results to an org hierarchy node, or within the `alter` stage to tag records with their hierarchy membership.
* **Cloud hierarchy structure**: The org hierarchy mirrors the native resource-organization model of each cloud provider. In every case the hierarchy stops at the container level — the leaf account, project, or subscription is not part of the path or the `id_path`. The `path_segments` argument is the ordered list of the display names of the container levels (not their IDs, and not the leaf), and `id_path` is the ID of the deepest container node in the path. Matching on `path_segments` alone selects the target container node and all of its descendants, which is useful for scoping to an entire OU, management group, or folder subtree.

  | Cloud Provider | Container Levels (org root → node)            | Leaf (not part of hierarchy path/id\_path) | Example Path                 | Example `id_path` (ID of deepest node) |
  | -------------- | --------------------------------------------- | ------------------------------------------ | ---------------------------- | -------------------------------------- |
  | AWS            | Organization → Organizational Unit (OU)       | Account                                    | `Acme Corp/Production`       | OU ID: `ou-a1b2-prod01`                |
  | Azure          | Management Group → (nested Management Groups) | Subscription                               | `Tenant Root Group/Platform` | Management Group ID: `mg-platform`     |
  | GCP            | Organization → Folder(s)                      | Project                                    | `acme.com/Production`        | Folder ID: `folders/574839201122`      |

## Examples

### Example 1: Scope to an AWS organizational unit

**Goal**: Return only the assets that belong to the AWS `Production` OU under the `Acme Corp` organization, including every account nested beneath that OU.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("Acme Corp", "Production"))
| fields asset_id, asset_name, cloud_provider, xdm.asset.hierarchy.path
| limit 3
```

**Explanation**: You apply a path-only match in a `filter` stage. The path contains only the container levels (organization and OU), so matching on `Acme Corp/Production` returns every asset in any account under the `Production` OU (and its sub-OUs), because the match is a prefix match.

**Output**:

| ASSET\_ID  | ASSET\_NAME      | CLOUD\_PROVIDER | XDM.ASSET.HIERARCHY.PATH     |
| ---------- | ---------------- | --------------- | ---------------------------- |
| i-0a1b2c3d | payments-api-01  | AWS             | Acme Corp/Production         |
| i-0e4f5g6h | orders-worker-02 | AWS             | Acme Corp/Production         |
| i-0i7j8k9l | billing-db-01    | AWS             | Acme Corp/Production/Billing |

### Example 2: Disambiguate an OU by ID

**Goal**: Two OUs are both named `Production` under different parents. Return only the assets under the specific `Production` OU whose ID is `ou-a1b2-prod01`.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("Acme Corp", "Production"), "ou-a1b2-prod01") = true
| fields asset_id, asset_name, xdm.asset.hierarchy.path, xdm.asset.hierarchy.id_path
| limit 3
```

**Explanation**: Because the OU name alone is ambiguous, you combine the path prefix (`Acme Corp/Production`) with the OU's ID as `id_path`. An asset is returned only when its path starts with `Acme Corp/Production` and its `id_path` equals `ou-a1b2-prod01`, so only the intended OU is matched.

**Output**:

| ASSET\_ID  | ASSET\_NAME       | XDM.ASSET.HIERARCHY.PATH | XDM.ASSET.HIERARCHY.ID\_PATH |
| ---------- | ----------------- | ------------------------ | ---------------------------- |
| i-0a1b2c3d | payments-api-01   | Acme Corp/Production     | ou-a1b2-prod01               |
| i-0m1n2o3p | payments-cache-01 | Acme Corp/Production     | ou-a1b2-prod01               |
| i-0q4r5s6t | payments-lb-01    | Acme Corp/Production     | ou-a1b2-prod01               |

### Example 3: Scope to an Azure management group

**Goal**: Tag assets that live under the Azure `Platform` management group (any subscription beneath it), starting from the `Tenant Root Group`.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| alter in_platform_mg = hierarchy_match(arraycreate("Tenant Root Group", "Platform"))
| fields asset_id, cloud_provider, xdm.asset.hierarchy.path, in_platform_mg
| limit 3
```

**Explanation**: You use a path-only match in an `alter` stage. In Azure the path contains the management-group chain (Management Group → nested Management Groups) and stops above the subscription, so matching on `Tenant Root Group/Platform` returns `true` for every asset in any subscription nested under the `Platform` management group, and `false` otherwise.

**Output**:

| ASSET\_ID   | CLOUD\_PROVIDER | XDM.ASSET.HIERARCHY.PATH        | IN\_PLATFORM\_MG |
| ----------- | --------------- | ------------------------------- | ---------------- |
| vm-web-01   | AZURE           | Tenant Root Group/Platform      | true             |
| vm-api-02   | AZURE           | Tenant Root Group/Platform/Prod | true             |
| vm-sales-03 | AZURE           | Tenant Root Group/Business      | false            |

### Example 4: Pin to a specific Azure management group by ID

**Goal**: Return only the assets under the `Platform` management group whose ID is `mg-platform`.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("Tenant Root Group", "Platform"), "mg-platform") = true
| fields asset_id, asset_name, xdm.asset.hierarchy.path, xdm.asset.hierarchy.id_path
| limit 3
```

**Explanation**: You combine the management-group path prefix (`Tenant Root Group/Platform`) with the management group's ID as `id_path`. Only assets whose path starts with `Tenant Root Group/Platform` and whose `id_path` equals `mg-platform` are returned — the ID pins the match to the exact management group.

**Output**:

| ASSET\_ID  | ASSET\_NAME      | XDM.ASSET.HIERARCHY.PATH   | XDM.ASSET.HIERARCHY.ID\_PATH |
| ---------- | ---------------- | -------------------------- | ---------------------------- |
| vm-web-01  | payments-web-01  | Tenant Root Group/Platform | mg-platform                  |
| vm-web-02  | payments-web-02  | Tenant Root Group/Platform | mg-platform                  |
| st-blob-01 | payments-storage | Tenant Root Group/Platform | mg-platform                  |

### Example 5: Scope to a GCP folder

**Goal**: Return only the assets that belong to the GCP `Production` folder under the `acme.com` organization, including every project nested inside that folder.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("acme.com", "Production"))
| fields asset_id, asset_name, cloud_provider, xdm.asset.hierarchy.path
| limit 3
```

**Explanation**: In GCP the path contains the organization and its folders and stops above the project. A path-only match on `acme.com/Production` returns every asset in any project inside the `Production` folder (and any sub-folders), because the match is a prefix match.

**Output**:

| ASSET\_ID     | ASSET\_NAME       | CLOUD\_PROVIDER | XDM.ASSET.HIERARCHY.PATH    |
| ------------- | ----------------- | --------------- | --------------------------- |
| gce-inst-01   | payments-prod-vm  | GCP             | acme.com/Production         |
| gce-inst-02   | orders-prod-vm    | GCP             | acme.com/Production         |
| gcs-bucket-01 | billing-prod-data | GCP             | acme.com/Production/Billing |

### Example 6: Pin to a specific GCP folder by ID

**Goal**: Return only the assets under the `Production` folder whose ID is `folders/574839201122`.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("acme.com", "Production"), "folders/574839201122") = true
| fields asset_id, asset_name, xdm.asset.hierarchy.path, xdm.asset.hierarchy.id_path
| limit 3
```

**Explanation**: You combine the folder path prefix (`acme.com/Production`) with the folder's ID as `id_path`. Only assets whose path starts with `acme.com/Production` and whose `id_path` equals `folders/574839201122` are returned, pinning the match to the exact folder even if another folder shares the same name.

**Output**:

| ASSET\_ID     | ASSET\_NAME          | XDM.ASSET.HIERARCHY.PATH | XDM.ASSET.HIERARCHY.ID\_PATH |
| ------------- | -------------------- | ------------------------ | ---------------------------- |
| gce-inst-01   | payments-prod-vm     | acme.com/Production      | folders/574839201122         |
| gce-disk-01   | payments-prod-disk   | acme.com/Production      | folders/574839201122         |
| gcs-bucket-02 | payments-prod-bucket | acme.com/Production      | folders/574839201122         |

### Example 7: Exclude a hierarchy node (negation)

**Goal**: Return all assets except those in the `Acme Corp/Sandbox` OU.

**XQL code**:

```sql
config timeframe = 1d
| dataset = asset_inventory
| filter hierarchy_match(arraycreate("Acme Corp", "Sandbox")) = false
| fields asset_id, cloud_provider, xdm.asset.hierarchy.path
| limit 3
```

**Explanation**: Comparing the result of `hierarchy_match()` to `false` inverts the match, so every asset that does not live under the `Acme Corp/Sandbox` container is returned. This is useful for excluding non-production or sandbox scopes from a query.

**Output**:

| ASSET\_ID   | CLOUD\_PROVIDER | XDM.ASSET.HIERARCHY.PATH   |
| ----------- | --------------- | -------------------------- |
| i-0a1b2c3d  | AWS             | Acme Corp/Production       |
| vm-web-01   | AZURE           | Tenant Root Group/Platform |
| gce-inst-01 | GCP             | acme.com/Production        |

## Related articles

* **Stages**: [`filter`](broken://pages/0084244cf5d7857507ebc54846595c8f8b973dea), [`alter`](broken://pages/d337cdc387c34a54f6c2c7b64a03e0044058e3da), [`fields`](broken://pages/ec11378723db46d8d955b98adea5348a20924bd4)
* **Functions**: [`arraycreate()`](broken://pages/ac84234df4be0ee671caabf262ab1547698d3799), [`wildcard_match`](broken://pages/c364933475c3c3874a0cfcdb720fde4a1d52b7af), [`coalesce()`](broken://pages/eff91c3d44e68e9d0f582f204b7fda89bdb62dae)
* **Datasets**: [`asset_inventory`](https://docs-cortex.paloaltonetworks.com/r/Cortex-XQL-Schema-Reference-Guide/Introduction)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/xql-command-reference-guide/readme/functions/hierarchy_match.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
