feat(search)!: serve a surfaced inline reference as a nested document - #689
Merged
Conversation
- store a surfaced (output) inline reference as a nested object, with one nested Physical Field per output field of its Reference Type (nestedFieldName), so a multi-valued reference keeps each referent's values grouped instead of smeared across parallel arrays - reconstruct it as a nested Search Document at the engine-adapter level, below every API surface, so a second surface inherits the nesting - add NestedDocument to SearchValue; a referent carries an id only when it is a named node - build the GraphQL reference type from the Reference Type's own output fields, with a nullable id, so a client selects a nested object's fields directly - reject a nested declaration the engine cannot serve at startup: an inline reference, and every field of a Reference Type, carries the Role output and nothing else - hand writerFor the schema, and take it as a collection-definition option, so a writer can declare the nesting
…t mid-run - require the schema in parseSearchResponse, so a caller cannot silently reconstruct nothing for every nested field - build the collection definition when a rebuild writer is constructed, so a surfaced inline reference without its schema throws there rather than inside the first run, under a held lock - declare the nested keyword fixtures array, matching what the projection writes for a path-valued keyword
…, not a list The projection wrote every path-valued keyword and reference field as an array whatever its `array` flag said, so one declaration meant a list to the projection and a scalar to the engine collection definition and the API output type. At root the engine rejected the document; inside a nested document, which the engine does not type-check, it survived to fail per query at the surface instead. - honour `array` for keyword and reference as every other kind already does: a declared array stores a list, a single-valued field the first value the graph carries - declare `array` on the fixtures whose sources are multi-valued
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.
Makes the API device of an Inline Reference real end to end: a Reference Type declared
inlinewithoutputis now stored, reconstructed and served as a nested object carrying its own Search Fields. A multi-valued reference keeps each referent’s values grouped, so a consumer never pairs parallel arrays by index, and a Deployment no longer flattens referents onto the root.Fix #674
What changed
@lde/searchSearchValuegainsNestedDocument– the referent of a surfaced inline reference, carrying anidonly when the referent is a named node (a nested document is read, not addressed).nestedReferenceType(schema, field)– the one predicate the collection definition, result reconstruction and the API surfaces share for “does this field carry a nested document?”.nestedFieldName(parent, name)– the nested Physical Field convention (media.contentUrl), the nested counterpart ofphysicalFields.searchSchemagains the invariants the nested shape needs, so an unserviceable nesting fails at startup, naming the field: an inline reference is either a reading device (no Role) or surfaced (output), and every field of a Reference Type carriesoutputonly –searchable/filterable/facetable/sortable/labelSourceare rejected, because no query compiler serves them and they would be silently ignored per query.arrayforkeywordandreferenceas it already did for every other kind: a declared array stores a list, a single-valued field the first value the graph carries. It previously wrote a list either way, so one declaration meant a list to the projection and a scalar to the collection definition and the API output type – at root the engine rejected the document, and inside a nested document (which the engine does not type-check) it survived to fail per query at the surface.@lde/search/testing) gains the nesting rule, so every engine implementation is held to it.@lde/search-typesenseobject/object[](turning onenable_nested_fields), with one nested Physical Field per output field of its Reference Type, allindex: false– nested content is display weight on disk, so the RAM lever is unchanged. It takes the schema as an option, and a rebuild writer builds its definition at construction, so a nesting type without its schema throws when the writer is built rather than inside the first run under a held lock.parseSearchResponsenow requires the schema, so a caller cannot silently reconstruct nothing for every nested field.@lde/search-api-graphqloutputfields (same per-kind rules as a root type, nullableid), so a client selects a nested object’s fields directly. Other references keep the id-plus-label pair.Wiring
searchIndexerPipeline’swriterForis called with the schema as well as the type, so a writer can declare the nesting;@lde/search-indexerpasses it through.Breaking changes
keyword/referencefield that does not declarearray: truenow projects a value rather than a one-element list. A Deployment whose source is multi-valued must declarearray: true– including on an internal field aderivecounts.SearchValuewidens: a consumer switching on a reference value must handle a nested document.parseSearchResponsetakes the schema as a required fourth argument.buildCollectionDefinitionthrows for a type surfacing an inline reference unless the newschemaoption is passed.searchSchema().Verified end to end against a real Typesense container (collection creation, import, search, reconstruction), including a mixed named/blank-node multi-valued reference and a referent missing an optional field.