Zoomed Image

Hierarchy Fields and the Within Comparator

Software Asset Management Guide
Customizing the Calculation

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:

  • DepartmentID
  • LocationID
  • CostCentreID

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:

  1. 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.
  2. Engine extension. Extending the engine's within branch 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:

  • LocationsDiscovery → Network → Location Hierarchy (locations have parent-child relationships)
  • DepartmentsAdmin → Lookup Tables → Departments (similar parent-child structure)
  • Cost CentresAdmin → 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.