feat(search)!: make path the whole statement of what projection reads#628
Merged
Conversation
- Drop the FramedNode argument from `derive`: a derive now computes only from the document projected so far, never the graph, so a field's `path` is the complete statement of what the projection reads. - Honour the no-role-means-internal promise for every kind via a shared `isInternalField` predicate: an internal field is projected so a later derive can read it, then pruned before the writer, and omitted from the Typesense collection definition (not stored, not indexed, no RAM). - Unexport the IR readers (`irisOf`, `literalsOf`, `firstLiteralOf`); they are now internal to projection. - Update the field-model docs and tests for the new behaviour.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Make a
SearchField’spaththe complete statement of what the projection reads from the graph, so a schema-driven extraction generator (#548) and its contract test become possible.Today
deriveclosures receive the framed node and read arbitrary predicates throughirisOf/literalsOf/firstLiteralOf, sopathis not the whole story – in the Dataset Register’sDatasettype, 13 of 23 predicates are readable only from inside a closure. A generator that emits a CONSTRUCT from the schema would silently miss every one of them.Changes
deriveloses itsFramedNodeargument – its signature is now(document) => unknown. A derive computes only from fields declared before it, never from the graph.pathsays what to read;derivesays what to compute from what was read.output/searchable/filterable/facetable/sortable) is an internal field: projected into the in-memory document so a later derive can read it, then pruned before the document reaches a writer, and absent from the engine collection definition – not stored, not indexed, no RAM. A new sharedisInternalFieldpredicate is the single source both the projection (prunes by it) and the Typesense collection definition (omits by it) use, so they cannot disagree. Previously only zero-roletextfields behaved this way; the other kinds wrote and declared unconditionally.irisOf,literalsOf,firstLiteralOf) – they are now internal to projection.packages/search/README.md, JSDoc) and the projection / collection-definition tests are updated for the new behaviour; test fixtures that previously relied on a zero-role field being projected now declare the role they actually intend.Breaking
Breaking for
@lde/search: the publicderivesignature changes and the three IR readers are no longer exported. Consumers migrate their derives to internal fields plusdocumentreads – e.g. the Dataset Register replacesirisOf(node, 'urn:dr:class')with a zero-roleclassesreference field whose value a derive reads off the document. That consumer migration is out of scope here (separate repo, gated on #548).Notes
Two pre-existing, degenerate edges are left as-is rather than widening scope: a field literally named
idwith no role would be pruned (anid-named field already clobbered the document key before this change), and adefaultSortingFieldpointing at an internal field would reference an omitted collection field (a default sort field should be sortable, hence never internal). Both belong in a separate declaration-validation change.Implements #607.