Skip to content

Developer notes

Overview · Installation · Configuration · Usage · FAQ

The add-on keeps its own inverted index in the store database (no external service):

Table Contents
?:kv_ils_objects One row per object and language: type (P product, C category, B brand variant, G page, V vendor), id, storefront/vendor, parent product, status, usergroups, title, subtitle, code, normalised title and code, popularity
?:kv_ils_words Normalised words per language with length and document frequency
?:kv_ils_postings Word → object with the summed field weight
?:kv_ils_grams Padded trigrams of every word (typo candidates)
?:kv_ils_synonyms, ?:kv_ils_stopwords Synonym groups and stop words per language
?:kv_ils_cache Suggestion answers (key, JSON, expiry)
?:kv_ils_meta Index revision, build state and run marks (never ?:storage_data)
?:kv_ils_queries, ?:kv_ils_clicks Daily analytics per storefront, language and phrase
?:kv_ils_rate Hourly per-IP counters of the tracking endpoint (salted hash, expire after 2 hours)

Normalisation: lowercase, accents and special letters folded (é → e, ß → ss, ı → i), separators split words, and hyphenated or dotted groups are also kept joined (T-Shirt → t, shirt, tshirt; USB-C → usbc). Product codes are also indexed without separators.

Field weights: name 10, product code 12, brand 6, categories 4, features 3, search words and meta keywords 3, descriptions 1 (optional). A word that appears in several fields gets the sum (capped at 40).

Upkeep: hooks re-index single objects at once; Builder::step() rebuilds in batches of 200 within a time budget (admin progress loop, --full=Y cron); Builder::update() picks up products by products.updated_timestamp and removes deleted objects (cron, “Update changed products”). A rebuild replaces objects in place and drops stale ones at the end, so the index stays usable. Every change bumps the index revision, which is part of the answer cache key.

For each query word: exact word (quality 1.0), longer words starting with it (0.6–0.9 by length ratio), synonyms (0.9) and, only when the word is unknown, typo candidates: words sharing padded trigrams, verified with the optimal string alignment distance (1 typo for 4–7 letters, 2 for 8+; swapped letters count as one; the last word of a dropdown query is also compared as a prefix). A word scores quality × posting weight per object; an object needs every word (or, when nothing matches all, all but one, with at least one word matched without a typo, × 0.7). Bonuses: exact product code +100, code prefix +20, title equal / starting with / containing the query +15 / +8 / +4, product popularity up to +4 (log scale), category/brand/vendor size up to +3.

On a catalog of 10,000 products (29,500 words, 95,000 postings) a dropdown query takes about 3 ms (p95 6 ms) in the engine; the visibility check and prices of the shown products add a constant 30–40 ms.

  • index:scripts post hook prints Tygh.kv_ils (endpoint URLs, language, currency, minimum length, texts) and js/addons/kv_instant_live_search/func.js. The output is identical for every visitor (full page cache safe). The script attaches to every form[name=search_form] input[name=q].
  • kv_instant_live_search.suggest (GET q, lang, cur): JSON {q, corrected, sections:[{type, items}], popular, fallback, all_url}. Products pass CS-Cart’s own visibility (fn_get_products with the candidate ids) and get prices with promotions (fn_gather_additional_products_data) for the shown products only. Answers are cached in ?:kv_ils_cache under md5(query, language, currency, storefront, usergroup set, index revision, settings revision, inventory settings). Guests’ default context is sent with Cache-Control: public, max-age=60; any other usergroup context with private, max-age=60, so customer-group prices never reach shared caches. Server-Timing reports the phases. The endpoint never writes the session.
  • kv_instant_live_search.track (GET e = s search, d dropdown search, c click; q, n results, t/id clicked object): 204, no-store, max 300 events per IP and hour.
  • Results page: get_products_pre replaces the core LIKE search (q) with the ranked ids for storefront calls with search_performed (up to 1,000 ids, variation and vendor-offer children add their parent); get_products adds products.product_id IN (...) and, unless the visitor chose another sorting, FIELD(products.product_id, ...) as the kv_relevance sorting; get_products_post restores q. Filters, pagination and other sortings stay core. products.post.php assigns the typo note and the no-results fallback; templates use the hooks products:search_results_mainbox_title and products:search_results_no_matching_found.

get_products_pre, get_products, get_products_post, products_sorting, dispatch_before_display, update_product_post, delete_product_post, update_category_post, delete_category_post, update_page_post, delete_page, update_company, delete_company, tools_change_status, update_product_feature_post, delete_product_feature (identical in 4.17.2 and 4.21.2).

php /path/to/store/admin.php --dispatch=kv_instant_live_search.cron # update changed products, clean up
php /path/to/store/admin.php --dispatch=kv_instant_live_search.cron --full=Y # full rebuild

The command prints a JSON summary.

fn_kv_instant_live_search_is_licensed() (Config::isActive(): add-on active, Enable instant search on, License\Client::isActive()) gates the storefront configuration, the suggest and track endpoints and the results-page ranking. When it is off the storefront uses the standard CS-Cart search; the admin page and the index upkeep keep working.

Path Purpose
app/addons/kv_instant_live_search/addon.xml Settings, tables
init.php, func.php Hooks, storefront configuration, install build, fn_kv_instant_live_search_is_licensed()
Tygh/Addons/KvInstantLiveSearch/Text.php Normalisation, words, trigrams, edit distance
Indexer.php, Builder.php Documents, index writes, full rebuild in steps, incremental update
Engine.php, Dictionary.php Query matching and ranking, synonyms and stop words
Suggest.php, ResultsPage.php Suggest endpoint with cache; results page integration
Analytics.php, Config.php, Meta.php Analytics, settings and gate, key/value marks
License/, controllers/backend/kv_instant_live_search_license.php License check (generated)
Upgrade/Synchronizer.php Self-healing upgrades (generated)
controllers/frontend/kv_instant_live_search.php, products.post.php Suggest and track endpoints, results page data
controllers/backend/kv_instant_live_search.php Admin page, rebuild steps, synonyms, analytics, cron
schemas/ Menu, permissions (vendors have no access)
var/themes_repository/responsive/templates/addons/kv_instant_live_search/ Script/config, results page hooks
js/addons/kv_instant_live_search/func.js, backend.js Dropdown (ARIA combobox, no external libraries); admin progress loop