Suggesting what to search for while it is typed
This guide shows you how to configure search settings and use the suggest endpoint to suggest field values in real time as a user types into a search box. Use this guide when building an autocomplete search box that suggests brands, categories, or other field values, marks the typed portion of the text, and updates suggestions on every keystroke.
The engine reads stored facet values from the answering generation. Enabling suggestions requires no reindex and is configured in the search settings of the index.
Prerequisites
Section titled “Prerequisites”Before you begin, ensure you have:
- A configured index with at least one
stringfield that hasfacetenabled and nohierarchy. - Credentials with the
indexes.readpermission to read settings, thesettings.writepermission to change them, and thesearchpermission to send suggest requests.
-
Check that the fields hold a dictionary:
Ensure the target fields are
stringfields configured withfacetand withouthierarchy. Configurefilteras well if you plan to let users search a picked suggestion as a filter chip:PUT /v1alpha1/admin/indexes/productsContent-Type: application/json{"fields": {"id": { "type": "string", "role": "id" },"name": { "type": "string", "role": "title" },"brand": { "type": "string", "filter": {}, "facet": {} },"category": { "type": "string", "filter": {}, "facet": {} }}} -
Opt the fields in through the search settings:
Send a
PUTrequest to update the search settings for the index. Include any existing settings, such asrankingorsynonyms, becausePUTreplaces the entire settings object:PUT /v1alpha1/admin/indexes/products/settingsContent-Type: application/json{"fields": {"brand": { "suggest": {} },"category": { "suggest": {} }}}To update a single field without replacing the entire settings object, send a
PATCHrequest:PATCH /v1alpha1/admin/indexes/products/settingsContent-Type: application/json{"fields.brand.suggest": {}}To disable suggestions for a field, set the path to
null.The server validates the fields against the active generation. Storing settings for a field that does not exist returns
settings:fields:field_unknown. Storing settings for a field that is not astringwithfacet, or that hashierarchy, returns HTTP 400settings:fields:suggest_unsupported. -
Ask for suggestions from the search box on every keystroke:
On each keystroke in the client search box, send a
POSTrequest to/v1alpha1/indexes/{name}/suggest. Debounce keystroke events on the client to avoid sending unnecessary requests while the user types quickly. You can scope suggestions using thefiltersproperty:POST /v1alpha1/indexes/products/suggestContent-Type: application/json{"text": "adi","filters": [{ "field": "category", "match": { "value": "Shoes" } }],"limit": 5}The engine returns matching values ordered by document count descending:
{"suggestions": [{ "text": "adidas", "typed": 3, "field": "brand", "value": "adidas", "count": 87 },{ "text": "Adidas Originals", "typed": 3, "field": "brand", "value": "Adidas Originals", "count": 12 }],"tookMs": 0.412} -
Render the suggestions:
Use the properties of each object in
suggestionsto display the list:- Use
typedto mark the first characters oftextapart from the rest, so the part already typed reads differently from the part that completes it. - Show
textas the engine answers it. It holds the label the search settings declare for the value in the locale of the request, where there is one. - Show a suggestion with
corrected: trueapart from the others. It was found one mistake away from what was typed, sotypedis0and nothing of it can be marked.
- Use
-
Search what was picked:
When the user selects a suggestion, execute a search query using the chosen item.
To search the suggestion as text, pass
textin atextclause:{"query": [{ "type": "text", "text": "adidas" }]}To filter on the selected field and value instead, the way a ticked filter does, pass a
fieldclause underfilters. The suggestion’sfieldandvalueare what the clause takes:{"filters": [{ "field": "brand", "match": { "value": "adidas" } }]}A field must have
filterenabled for this; see step 1. -
Configure typos, limits, locales, and labels:
Adjust the suggest request parameters to fit your search requirements:
- Typos: By default,
typosis"auto", which tolerates one mistake for queries of 5 or more characters when fewer exact matches thanlimitexist. Set"typos": "off"to require exact prefix matches only. - Limit: Set
limitto an integer between 1 and 100 (default: 5) to control the maximum number of suggestions returned. - Locale and labels: Pass a BCP-47 tag in
localeto pick the labels declared underfields.<name>.valuesin the search settings. The engine compares the typed text with the labels of that locale as well as with the stored values, and answers the label intextandlabel. Withoutlocale, the labels of each field’s default locale are used. See Declared values.
- Typos: By default,
-
Monitor and operate suggestions:
Keep the following operational behaviors in mind:
- Timeouts: The timeout for suggest requests is governed by
EXOFIND_SUGGEST_TIMEOUT(propertyexofind.suggest.timeout, default2s). When a request exceeds this duration, the server returns HTTP 503search:timeout. - Metrics: Track suggest request duration and outcomes with the
exofind.suggesttimer metric, which recordsoutcome(successorerror) and optionallyindex. - Warming: After each index reopen, background warm threads configured by
EXOFIND_SEARCH_WARM_THREADSbuild the folded dictionary for each suggested field. If warming is set to0, the first request after a reopen builds the folded dictionary. - Memory cost: Each suggested field keeps a folded dictionary per segment, at about the folded bytes of its distinct values plus 8 bytes per value, counted in
exofind.facet.state.bytes. Opt in the fields a shopper types towards, such as brand and category. A free-text field costs its whole vocabulary per segment.
- Timeouts: The timeout for suggest requests is governed by
Confirming the result
Section titled “Confirming the result”Verify that suggestions are returned correctly by sending a request with a partial term:
POST /v1alpha1/indexes/products/suggestContent-Type: application/json
{ "text": "adi"}Check the response:
suggestions: Contains matching values from opted-in fields, withtypedindicating the length of the matched prefix andcountreflecting the number of matching documents.tookMs: Shows the execution duration in milliseconds.
If suggestions is empty, check the following causes:
- No fields opted in: Verify with
GET /v1alpha1/admin/indexes/products/settingsthatfields.<name>.suggestis present for the target fields. An index with no suggested fields returns an empty list with HTTP 200. - Prefix does not match start of value: The engine matches the start of the entire value, not individual words inside the value. For example,
airdoes not matchNike Air Max. - Generation mismatch: If a newly promoted generation omits the field or lacks
facet, the engine skips the field. Check the node logs for skipped field warnings. - Unsupported node capability: If a node lacks the
suggest_valuescapability, it ignores the settings and returns no suggestions. Check theunsupportedFeatureslist in the settings response.
Related
Section titled “Related”- Suggesting what to search for - Suggest request fields, matching rules, and response structure.
- Field settings - Configuring
suggestand declared values on fields. - Reading colours and brands in the search box - Interpreting facet values directly from full search query strings.
- Searching from a search box - Running the search once the person accepts a suggestion or keeps typing.
- Errors - Error codes returned by search and admin APIs.
Exofind is built by Level Four AB and is available under the Apache License 2.0.