You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A polymorphic reference – a lookup naming more than one target, as #717 delivers – can never be joinable: a Typesense reference field names one target collection, and ids that live in two collections have no single collection to reference. So a join predicate on such a reference is out of reach: a filter evaluated on the referent’s own document rather than on the referring one, such as “works whose creator died before 1900” or “whose creator is located in Maastricht”.
#717 delivers everything else – labels, per-type output fields, __typename, id filters and facet buckets all work from the referring document plus the batched lookup. This issue holds the one capability it leaves out.
Three ways to recover it
Set out in #717; repeated here so the trade-off stays in one place.
A. A shared collection of the common fields. An agents collection carrying what Person and Organization share, reached by a single-target reference. The intersection is essentially label, so this restores a join over precisely what the lookup already gives and leaves per-type filters unreachable. Fixes the mechanism, recovers no functionality.
B. The same collection denormalised to the union of fields.agents carries birthDateandlocation, each absent for the kind it does not apply to, plus a discriminator. Joins work over per-type fields; the resolver reads the discriminator and returns the matching per-target type with only the fields that apply. Asks least of the engine. Costs: a second copy of every agent in RAM, two copies to keep in step (a second provenance stamp, inheriting Single-valued provenance stamp: shared entities lose sources and can be swept while still contributed #697 in a second place), sparsity rules for sort_by and for a filter that only one type can satisfy, a defined answer for a node co-typed with two merged classes, a rule for field-name collisions, and a rebuild whenever the merged set changes.
C. One reference field per target, disjoined at query time.creator → persons.idandcreator → organizations.id; each document resolves in one and dangles in the other, and the predicate compiles to $persons(…) || $organizations(…). No new collection and per-type fields survive. Rests on two behaviours to verify against Typesense first: whether a permanently dangling async_reference is tolerated, and whether two joinable fields on one root type pointing at different collections coexist – ADR 19’s one-edge rule is keyed per target collection, so the second looks safe, but was not measured.
Not now
No deployment has asked for a filter on a referent’s own properties through a polymorphic reference. Until one does, a multi-target lookup refuses joinable at schema validation, as inline and local already do, and ADR 27 points here.
Summary
A polymorphic reference – a
lookupnaming more than one target, as #717 delivers – can never bejoinable: a Typesense reference field names one target collection, and ids that live in two collections have no single collection to reference. So a join predicate on such a reference is out of reach: a filter evaluated on the referent’s own document rather than on the referring one, such as “works whose creator died before 1900” or “whose creator is located in Maastricht”.#717 delivers everything else – labels, per-type output fields,
__typename, id filters and facet buckets all work from the referring document plus the batched lookup. This issue holds the one capability it leaves out.Three ways to recover it
Set out in #717; repeated here so the trade-off stays in one place.
agentscollection carrying whatPersonandOrganizationshare, reached by a single-target reference. The intersection is essentiallylabel, so this restores a join over precisely what the lookup already gives and leaves per-type filters unreachable. Fixes the mechanism, recovers no functionality.agentscarriesbirthDateandlocation, each absent for the kind it does not apply to, plus a discriminator. Joins work over per-type fields; the resolver reads the discriminator and returns the matching per-target type with only the fields that apply. Asks least of the engine. Costs: a second copy of every agent in RAM, two copies to keep in step (a second provenance stamp, inheriting Single-valued provenance stamp: shared entities lose sources and can be swept while still contributed #697 in a second place), sparsity rules forsort_byand for a filter that only one type can satisfy, a defined answer for a node co-typed with two merged classes, a rule for field-name collisions, and a rebuild whenever the merged set changes.creator → persons.idandcreator → organizations.id; each document resolves in one and dangles in the other, and the predicate compiles to$persons(…) || $organizations(…). No new collection and per-type fields survive. Rests on two behaviours to verify against Typesense first: whether a permanently danglingasync_referenceis tolerated, and whether two joinable fields on one root type pointing at different collections coexist – ADR 19’s one-edge rule is keyed per target collection, so the second looks safe, but was not measured.Not now
No deployment has asked for a filter on a referent’s own properties through a polymorphic reference. Until one does, a multi-target lookup refuses
joinableat schema validation, asinlineandlocalalready do, and ADR 27 points here.Related