Understand search

How search works

Index, query, ranking, facets — and what each one depends on.

A search engine does not search your catalog. It searches a copy of your catalog that it built earlier, in a shape it likes. Almost everything that goes wrong with B2B search goes wrong in that copy — which is why this article starts there and not at the search box.

The scenario

A maintenance technician has a hand-written note: Sechskantschraube DIN933 M8x40 A2. He types it into your shop. Four things now have to line up:

  1. Every one of those products has to be in the index.
  2. The engine has to cut the query into pieces it can match — and M8x40 has to survive that cut.
  3. It has to rank the right screw above the 380 other screws.
  4. The buyer has to be able to narrow what comes back — thread, length, material — without typing anything else.

Index, tokenisation, ranking, facets. If any one of them is wrong, the technician phones your Innendienst, and everything you spent on the shop bought you a phone call.

The index is a flattened copy of the catalog

Your catalog is normalised: a product row, attribute values in their own structure, options in another, categories in a join table. That shape is right for editing and wrong for searching. Nobody can answer "stainless fittings rated above 100 bar, sorted by relevance, with counts per thread size, in 40 milliseconds" out of it.

So the platform builds a second, denormalised copy — the index. One document per product, with everything already resolved: the German name, the English name, the manufacturer's name spelled out rather than referenced, the category paths, the option labels, the numeric values as numbers.

Two consequences follow, and both surprise people:

  • The index is always slightly behind. It is updated from catalog events, not read live. Normal lag is seconds; after a bulk import, minutes. See Common search problems.
  • Search quality is data quality. The engine can only match what is in the document. If pressure_rating is empty on 300 products, no ranking configuration makes those 300 findable by pressure. If material is written as V4A, 1.4571 and Edelstahl on different products, the facet splits into three and each part looks small and useless.

This is the sentence worth carrying out of this article: search is a lens on your catalog, and a lens cannot add detail that is not there. Every hour spent on data quality improves search more than an hour spent on search configuration.

Tokenisation: why DIN933 M8x40 is hard

Before it can match anything, the engine cuts text into tokens. By default it cuts on spaces and punctuation. That default is built for prose, and B2B buyers do not type prose.

What is typedNaive tokensWhat the buyer meant
M8x40m8x40thread M8, length 40
DIN933din933norm DIN 933
4711-A4711, athe article 4711-A, exactly
G 1/2"g, 1, 2thread size G 1/2
Sechskantschraubeone tokenSechskant + Schraube

Two separate problems hide in that table.

Codes must not be shredded. 4711-A cut into 4711 and a will match every article starting with 4711 and rank them by chance. The fix is to tell the engine which symbols are part of a code rather than separators, and which are separators that should also keep the whole string. Both 4711-A and 4711 then find the article, and the exact string wins.

German compounds must not be atomic. Schlauchschelle, Edelstahlrohr, Sechskantschraube — German glues words together, and a buyer who types Schraube gets nothing if the product is only called Sechskantschraube. Search engines split compounds badly or not at all, in every product on the market. There is no toggle that fixes German. What actually works is boring: a synonym list built from real queries, plus the decomposed words present in the product's own data. See Synonyms, stop words and rules.

Do not solve tokenisation with typo tolerance. Typo tolerance is what lets Verschraubng find Verschraubung. Applied to part numbers it is actively harmful: with one typo allowed, 4711-A also matches 4711-B and 4712-A, which are different articles with different prices. Codes must be matched exactly, with typo tolerance switched off for those fields.

Ranking: what "best match" means

When 40 documents match, something has to decide the order. Real engines combine several signals:

SignalWhat it meansWhere it matters in B2B
Text match scoreHow well, and in how many fields, the query matchedThe baseline
Field weightA hit in sku counts more than a hit in descriptionDecisive — see Configure the index
Exact matchThe whole query equals the whole fieldThe part-number case
Token positionMatched early in the fieldNames beat buried description text
Business rulesOwn brand, in stock, margin, contract articleMerchandising
CurationA human pinned this result for this queryThe override of last resort

The order of those signals is a policy decision, not a technical one. A B2C shop ranks by conversion probability. A technischer Großhandel ranks by identity first: if the query looks like a code and a code matches, that article is result one and nothing outranks it. Everything else is negotiable.

Facets come from filterable attributes

A facet is a filter with counts — Material: V4A (212). It is not something the storefront invents. The engine can only aggregate over fields that were declared as facet fields when the index was built, and those come directly from attributes you marked filterable in the catalog.

That is the whole chain, and it is worth memorising because it explains most "why is this filter missing" tickets:

attribute exists → attribute is filterable → attribute is in the index as a facet field → the storefront can render it → the buyer sees it

Numeric facets are the same chain with one extra step: a measurement attribute stores a value and a unit, and the index stores the value converted to the standard unit so that a range filter of 100–250 bar compares like with like. This is why storing 10 in a plain number field and the word "bar" somewhere else quietly removes that attribute from search forever.

Search is per channel and per locale

One index does not serve everyone.

  • Per locale. A German document and an English document tokenise differently, contain different text, and need different synonyms. A buyer on the English storefront searching hexagon bolt must not be ranked against German descriptions.
  • Per channel. A channel is a distinct cut of the catalog. A punchout catalog for one large customer contains their negotiated assortment and nothing else. If search ignored the channel, that buyer would find articles they are not entitled to buy — and then call to ask why they cannot order them.

Customer-specific assortments go one step further: the same channel, filtered per organization. The platform enforces that at query time by binding the filter to the search credential the storefront is issued, so a buyer cannot remove it by editing the URL.

How this works in the Revenue Cloud

  • The engine is Typesense, self-hosted on the platform's own infrastructure. Nothing about your catalog leaves it — the reason a SaaS search provider was not an option under DSGVO.
  • The index is defined per app. The products app declares which fields exist in the search document, which are searchable, which are facets and which are sortable. You configure behaviour; you do not maintain plumbing.
  • Updates arrive as events. A product change is published as an event and applied as a single-document update. There is no nightly rebuild in normal operation.
  • Schema changes rebuild into a new index and swap. Adding a facet field means the index is built again alongside the live one and switched over atomically, so there is no window where search returns nothing.
  • The search service is visible under App Studio › Services › Search, with its collections and their document counts. That screen is where you confirm the index exists and is populated before you debug anything else.

Next