Skip to content

Docs: clarify whether formulas support multi-hop traversal (probed: no, single-hop only) #4

Description

@mitselek

Summary

The Formulas docs describe single-hop references (propertyName.*.property, _child.typeName.propertyName, _referrer.typeName.propertyName) but don't say anything about chained / multi-hop traversal. I ran a live probe to find out — multi-hop doesn't work with any of the syntaxes I tried. The docs should explicitly say so (and a feature request for multi-hop is worth considering separately).

What I tested

Created four entity types chained by parent: probe_gpprobe_pprobe_c, plus a probe_referrer type with a reference property cref → probe_c and several formula properties using different syntaxes:

Formula Expected result Actual
cref.*.name "C-instance" (1 hop via ref) "C-instance"
cref.*._parent.*.name "P-instance" (2 hops: ref → parent → name) ❌ absent
cref.*._parent.probe_p.name "P-instance" (2 hops, typed at second step) ❌ absent
cref.*._parent.*._parent.*.name "GP-instance" (3 hops via ref+parents) ❌ absent
cref.*._parent.probe_p._parent.probe_gp.name "GP-instance" (3 hops, all typed) ❌ absent

Only single-hop resolved. All multi-hop variants left the formula property unwritten (no value at all — not an error, just absent).

Suggested doc change

Under Formulas → Field References, add a note:

Formulas support single-hop traversal only. A reference like myref.*.property resolves the property on the directly-referenced entity. Chaining further hops — e.g., myref.*._parent.*.name or myref.*.otherref.*.name — is not supported; such formulas evaluate to undefined and the property is not written. To bring in data more than one hop away, denormalize the value into the closer entity (app-level on save, or via a separate single-hop formula on the intermediate entity).

Use case (why this came up)

We're designing a lending entity for Polyphony's Entu schema. A lending references a copy; copy parents under edition; edition parents under work. To show the work title in lending.name, we'd need to traverse lending.copy → copy._parent → edition._parent → work.name — three hops.

With multi-hop unavailable, options are:

  1. Live with single-hop only in lending.name (e.g. member.*.name copy.*.name CONCAT_WS ' — ' produces "Alice Smith — Copy #3" — no work title).
  2. Denormalize work title onto copy via a single-hop formula (copy.work_title = _parent.*.name), then reference it from lending (copy.*.work_title). Two single-hops chained via materialization, since the intermediate edition isn't strictly needed for the title.
  3. Maintain lending.name in app code on creation — bypasses formulas entirely.

Workable, but the multi-hop unavailability is a real constraint for designers — easy to assume it works given the natural-looking syntax, then have formulas silently produce nothing.

Feature thought (separate from the docs ask)

A multi-hop syntax would be a real UX win for normalized schemas. Two natural options:

  • Dot-chained: cref.*._parent.*.name (what I tried — already-natural syntax, just needs implementation)
  • Explicit chain operator: cref CHAIN _parent CHAIN name or similar — more verbose but disambiguates from property-path-with-dots

Up to the Entu team whether either fits the formula DSL's philosophy. Filing as a thought, not a hard request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions