How search works
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:
- Every one of those products has to be in the index.
- The engine has to cut the query into pieces it can match — and
M8x40has to survive that cut. - It has to rank the right screw above the 380 other screws.
- 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_ratingis empty on 300 products, no ranking configuration makes those 300 findable by pressure. If material is written asV4A,1.4571andEdelstahlon 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 typed | Naive tokens | What the buyer meant |
|---|---|---|
M8x40 | m8x40 | thread M8, length 40 |
DIN933 | din933 | norm DIN 933 |
4711-A | 4711, a | the article 4711-A, exactly |
G 1/2" | g, 1, 2 | thread size G 1/2 |
Sechskantschraube | one token | Sechskant + 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.
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:
| Signal | What it means | Where it matters in B2B |
|---|---|---|
| Text match score | How well, and in how many fields, the query matched | The baseline |
| Field weight | A hit in sku counts more than a hit in description | Decisive — see Configure the index |
| Exact match | The whole query equals the whole field | The part-number case |
| Token position | Matched early in the field | Names beat buried description text |
| Business rules | Own brand, in stock, margin, contract article | Merchandising |
| Curation | A human pinned this result for this query | The 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
- How B2B buyers actually search — the query patterns this all has to survive.
- Configure the index — which attributes are searchable, and weighted how.