The ranking cascade
The eight tiers that decide result order, each one only breaking ties the tier before it left.
suo ranks results with a cascade, the same shape Algolia and Meilisearch use: eight tiers, evaluated in a fixed order, where each tier only decides between hits the tiers above it could not separate. A hit's full ranking vector is available on every result — this is what the playground's "why this rank" panel shows.
The eight tiers
- Pinned — a query-time pin rule places this exact record at a fixed position, above everything else.
- Words matched — how many of the query's words were found at all, regardless of typos.
- Typos — fewer typo corrections beats more; an exact match beats a corrected one.
- Proximity — how close together the matched words appear in the text.
- Attribute — which searchable tier the match came from, and where in it (a title match outranks a body match).
- Exactness — an ICU whole-word match outranks a prefix match, which outranks a bigram-only match (CJK recall floor — see CJK). While someone is still typing, the last word is unfinished, so a word that starts with it counts as a whole-word match: typing
wegives "Weekly" the same exactness as "we", and the other tiers decide between them. - Custom ranking — your own tie-breaking sort, for example by recency or popularity.
- bm25 — a standard relevance score, as the final tiebreaker.
Why a cascade instead of one score
A single blended score is hard to reason about: why did result B beat result A? A cascade answers that directly — "B matched one more word than A" is the whole explanation, at tier 2, and nothing below tier 2 needed to run. This is also why custom ranking sits near the bottom: it should break ties among equally relevant results, not override relevance itself.
Reading the response
Pass explain: true on a search to get this vector, plus decidedAgainstNextBy — which tier actually separated this hit from the next one — on every hit. See Search.
Typos are lazy
Typo expansion only runs when the exact and prefix candidates come up short — see Typo tolerance for the exact thresholds. This keeps a query that already has plenty of exact matches fast, and keeps a typo'd query from drowning out an exact one.