Join Filter Pattern
When joining two object types — for example, FamilyInstances to their FamilySymbol — some instances may not have a matching symbol in the filtered set. The join filter pattern uses a ternary with () to silently drop non-matching elements from the output.
The problem
A lookup returns undefined when no match is found. If you include that in the output, you get null fields or broken objects. What you actually want is for the element to disappear entirely from the results.
The pattern
After looking up the related object, return a structured result if found — or () if not:
(
$symbols := $[type = "FamilySymbol" and values.category.type = "Model"];
$symIndex := $merge($symbols.{ $string(id): $ });
$[type = "FamilyInstance" and $exists(parent)].
(
$sym := $lookup($symIndex, $string(parent.id));
$sym ? {
"id": id,
"name": name,
"symbolName": $sym.name,
"assemblyCode": $sym.values.assemblyCode
} : ()
)
)
() is an empty expression — it produces no output. Elements where $sym is undefined are excluded from the result array entirely.
Why () and not null
Returning null would include the element with a null value, which could cause false positives in the validator. Returning () makes the element disappear, as if it was never in the dataset.
When to use this pattern
Use this when: - You join FamilyInstances to a filtered subset of FamilySymbols - Not all instances will have a matching symbol in the filtered set - You want those unmatched instances silently excluded
Do not use this when: - The absence of a match is itself a validation finding — in that case, include the element with a computed field that the validator checks
Relation to the applicability gate
The join filter pattern and the applicability gate both remove elements from the output. The difference:
Join filter ($sym ? {...} : ()) |
Applicability gate ([field = true]) |
|
|---|---|---|
| Trigger | Lookup returned nothing | Computed field is false |
| Position | Inside .() expression |
After the projection |
| Typical use | Cross-type join | Conditional rule scope |
Common mistakes
- Using
$sym != null ? {...} : null— returningnullkeeps the element in the array with a null value - Forgetting
$exists(parent)before the lookup — instances without a parent will throw an error on$string(parent.id)