Hierarchy Fields and the Within Comparator
The within comparator lets a rule match parent-child relationships — "London Floor 2 is within London." This page explains how within works, which fields support it, and the constraints when using it in custom rules.
What within Does
For three specific xAssets fields — DepartmentID, LocationID, CostCentreID — there is a parent-child hierarchy stored in the database. The within comparator walks that hierarchy.
Affinity Consumption.LocationID within License.LocationID, 400
Read: "the consumption's location is within (or equal to) the license's location, in the location hierarchy." This matches when:
- Consumption location = License location (exact match — also matches
=) - Consumption location is a child of License location at any depth
- Consumption location is a grandchild, great-grandchild, etc.
It does not match when the consumption is a sibling, an ancestor, or in a different tree entirely.
Which Fields Support within
The comparator is hardwired in the engine for exactly three fields:
DepartmentIDLocationIDCostCentreID
Calculated fields, custom spec fields, or any other field — even if they reference one of the hierarchy IDs — do not participate in within.
This means the scoping pattern in Per-Product Scoping cannot use within on its synthetic DeptScope field. Only the three native hierarchy fields work.
Exact vs Within Scoring
The default rules use both = and within on the same field with different weights, so exact matches outrank hierarchy matches:
Affinity Consumption.LocationID = License.LocationID, 800
Affinity Consumption.LocationID within License.LocationID, 400
A consumption at "London Floor 2" with a license at "London Floor 2" gets +800 (exact) plus +400 (within) = +1200. A consumption at "London Floor 2" with a license at "London" gets only +400 (within). The exact-match license wins by 800 points.
This pattern — both = and within on the same field with different weights — is the standard way to express "exact is best, hierarchy is acceptable" preferences.
Within in Requirements
The shipped location requirement uses within:
Requirement Consumption.LocationID within License.LocationID
This is what makes location scoping work. A license set to "London" covers any consumption in London or its children. A license set to "Bath" covers Bath and Bath's children. A license with no location set has no constraint.
If you want stricter location matching as a requirement (exact-only), use =:
Requirement Consumption.LocationID = License.LocationID
But be aware this is much stricter — a London-Floor-2 asset will not be covered by a London-wide license, only by one explicitly set to London Floor 2.
When the Hierarchy Constraint Bites
The hardwired hierarchy support means two patterns do not work:
Pattern 1: Custom hierarchy field
You add a BusinessUnitID field with its own hierarchy. You cannot use within on it — the comparator is hardwired to the three known fields. You can use = for exact matching only.
Pattern 2: Hierarchy through synthetic gate
The per-product scoping pattern produces a synthetic field (e.g., DeptScope). Even though it derives from DepartmentID, the synthetic field is not in the wired list. You can only compare it with =.
For both patterns, the workarounds are:
- Pre-flatten in SQL. In the data source query, emit one row per ancestor in the hierarchy. Equality matching then picks up parent matches naturally. This blows up the working set but needs no engine change.
- Engine extension. Extending the engine's
withinbranch to support virtual hierarchy fields is a code change and outside the scope of customer customization.
Worked Example: Location Hierarchy
Asset DONNA-PC at "Bath Floor 2".
| License Location | = matches? |
within matches? |
|---|---|---|
| Bath Floor 2 | Yes (exact) | Yes (also exact, which is "within or equal") |
| Bath | No | Yes (Bath Floor 2 is within Bath) |
| Bath Floor 1 | No | No (sibling, not ancestor) |
| London | No | No (different tree) |
| (no location) | No | Yes (no constraint) |
The "no location" case is special: a license with no location set passes any within requirement. This is what makes the default location requirement non-disruptive — you only constrain a license by setting its location explicitly.
Hierarchy Setup
The three hierarchies are configured under different menus:
- Locations —
Discovery → Network → Location Hierarchy(locations have parent-child relationships) - Departments —
Admin → Lookup Tables → Departments(similar parent-child structure) - Cost Centres —
Admin → Lookup Tables → Cost Centres
When you change a hierarchy (e.g., move a department under a different parent), recalculation will pick up the new structure on the next run. Existing transactions are not retroactively re-evaluated unless you recalculate the relevant period.