Repository navigation
Rank API search by the best role of each typed word - #4699
Merged
Merged
Conversation
This was referenced Nov 4, 2026
Contributor
Docs preview (local build)Handbook preview: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/4699/ Sample changed pages: |
Two plain words were read as an operation plus a field, and the operation half had to be an endpoint, so `cluster flat_settings` found no field rows. Each word now picks its best role on an operation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The API lookup names every role option per word. A word that matched an endpoint as well as a field prefix, such as `search` in `search retriever`, no longer lists `search_type` rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds first-result and field-row cases for queries the operation-plus-field readings missed, and an explicit report of the top three hits with each word's winning role for whoever tunes the weights next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the two cluster flat_settings first-result cases, where four tied operations make the first result arbitrary. Loosen the three-word case to what the index guarantees. Limit the relevance report source to the fields the document type requires. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… first Four Cluster operations take `flat_settings` and tie on every signal, and the specificity prior puts `GET /_cluster/state` first, so the docs no longer claim `GET /_cluster/settings` as the result of `cluster flat_settings`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`snapshot restore` ranked `snapshot-create` first. Its path minus parameters is exactly `_snapshot`, while `snapshot-restore` only has `_snapshot/*/*/_restore`. A plain word now also matches endpoints under its `_name` at 5.5, just below an exact endpoint at 6.0. So `snapshot restore` finds `snapshot-restore`, and a bare `search` still prefers `_search` over `_search/scroll`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each word adds a dis_max with a nested inner-hits query to a request sent on every keystroke, so a pasted paragraph built a very large query. The cap mirrors the eight path segments an endpoint query reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The api.method field holds only the spec's canonical verb, so a pasted request line such as `POST /_count` found nothing: POST was a required word that the count operation, canonically GET, cannot explain. The method now joins the path it precedes and only lifts operations whose verb matches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
reakaleek
force-pushed
the
api-search/token-roles
branch
from
November 4, 2026 22:34
89a4679 to
958d9cb
Compare
This branch was successfully deployed
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.
The API search box now explains each typed word by the best thing it names about an operation, so
cluster flat_settingsandes|ql drop_null_columnslist the Cluster and ES|QL operations with their parameter rows, where they used to return body matches with no rows. Word order no longer matters, and a field row shows only under a word that matched a field.Affects: Search
Prompt summary: The API search box ranks
search retrieverperfectly but returns bogus results forcluster flat_settingsand nothing useful fores|ql drop_null_columns, although both are real query parameters. Asked why, and then asked to design the fix properly instead of patching the rule, the work became a per-token query model delivered as a stack of three changes. This is the middle layer, the query and the result rows.Why
The old query read two plain words as "operation + field" in both orders and required the operation half to be an endpoint key.
searchworked only because its underscore alias_searchis a key.clusterandes|qlare not keys (the keys are_cluster/settings,_queryand so on), so both readings were dropped, the nested field query never ran, and the body match at boost 0.1 decided the list. The same design summed the lexical branch with the readings, so an operation whose title held both words and that also had a field named like one of them was paid twice for one word, and ties inside a group of correct operations fell to body noise.What
One role per word
ApiLookupQueryBuildersplits the query on whitespace, reads at most its first eight words, folds a method typed before a path into that path (the typed verb lifts operations with that canonical method instead of being a required word, so a pastedPOST /_countstill finds the count operation), and gives each word onedis_maxover the things it can name, each a namedconstant_score: an endpoint key (6.0 for the typed value and its_alias, 5.5 for the routes under that alias, sosnapshotalso covers_snapshot/{repository}/{snapshot}/_restore), a word of the operation id or path (2.0, fromapi.words), the group (1.0), a word of the title (1.0), the HTTP method (0.5), a field name (1.0 exact, 0.6 prefix, with the dotted-path and trailing-dot children options as before) and a word of the description (0.1). Up to two words must all be explained; from three on, 75 percent, which replaces the separate loose clause. Whole-query lifts keep a title that holds every word (3.0), a title that starts with the typed text, the children of a typed path, the navigation rank features, and two priors that break ties deterministically: fewer operation id words and not deprecated.ApiLookupWeightsholds the table and states the measured invariants between the weights.Field rows follow the winning role
The request asks Elasticsearch for the score of each named query.
ApiLookupRoles.Resolvepicks the best role per word, andSearchResultProcessorlists a word's inner hits only when that word named a field at least as well as anything else, sosearch retrieverlistsretrieverbut notsearch_type.The docs-wide search is untouched
Only
type=apirequests take the new builder. Every other filter builds the same lexical query and identifier field reading as before. The docs page for the API explorer describes the new rule.Verify
Against a cluster that has the index fields from the layer below (
DOCUMENTATION_ELASTIC_URL,DOCUMENTATION_ELASTIC_APIKEY,ENVIRONMENT=dev,DOCS_BUILD_TYPE=assembler):On dev after reindexing with the layer below, all 32 API cases pass, 22 of 23 holdout queries the weights were never tuned on rank as expected (the one miss is a tie between datafeed operations), and the 13 docs-wide first-result failures are the identical list on the previous dated index, so nothing outside the API lookup moved. The served site shows the three reported queries with their rows.
Risk: the query reads
api.words,api.groupandapi.id_words, which exist only on indices written after the layer below. On an older index arank_featurequery on the unmapped field returns normally and thematchroles match nothing (measured on the previous dated dev index), so until the next index run the lookup falls back to the endpoint, title and field roles and nothing errors.Out of scope: the deletion of the old readings from
SearchQueryBuilder(the next layer), a prose-gated semantic branch (measured and deferred), a popularity prior for the ties that specificity does not break, and field names split on underscores soflat settingsfindsflat_settings.Stack: 2 of 3, on top of #4698; #4700 removes the legacy readings on top of this branch.
🤖 Generated with Claude Code