Relevance Scoring: Really Understanding BM25
AI generated
_doc
_index
Elasticsearch · OpenSearch · Relevance Scoring
Relevance Scoring
really understanding BM25

BM25 is the default scoring algorithm of Elasticsearch and OpenSearch, yet most developers only know the name, not the mechanics behind it. Term frequency, inverse document frequency, and field length normalization together determine why one document ranks higher than another, and anyone who understands these three factors can diagnose relevance problems on purpose instead of merely guessing.

17 min read BM25 · TF-IDF · Term Frequency · IDF · Field Length Normalization Elasticsearch 8.x · OpenSearch 2.x

1. Why relevance scoring is necessary at all

As soon as a search request returns more than a handful of hits, it is not enough to know which documents match, you also have to decide in what order to display them. That is exactly what relevance scoring is for: every hit document gets a numeric score expressing how well it matches the search request, and the result list is sorted descending by that score. The algorithm that computes this score by default in Elasticsearch and OpenSearch is called BM25, short for "Best Matching 25", a name that traces back to a series of retrieval functions from information retrieval research.

BM25 replaced the older TF-IDF-based scoring as the default starting with Elasticsearch 5, because it delivers more robust relevance results in practice, especially with documents of varying length. Anyone who wants to understand why a particular product appears above another in a search has to understand what the BM25 score is made of: term frequency, inverse document frequency, and field length normalization.

The name BM25 itself already reveals part of the story: it comes from a series of experimental retrieval functions called "Okapi", developed in the 1980s and 1990s at London's City University, where the 25th variant proved especially robust and has since become the de facto standard in text search. This decades-long track record in practice is a key reason BM25 today serves as the starting point for relevance scoring in practically every modern search engine, not just Elasticsearch.

These three components are not an academic curiosity, they have direct practical consequences. A user wondering why a product with the search term in its title is not at the very top will almost always find the answer in one of these three factors. The sections that follow explain each one individually and then show how they work together in the complete BM25 formula.

It is also important to draw a clear boundary: BM25 does not replace the Bool Query or the Match Query, it complements them. While Bool Query and Match Query determine which documents qualify as hits at all, BM25 exclusively determines the order of this already-fixed set of hits. This clean separation between the hit set and its ordering is a central architectural principle of Elasticsearch that runs through the entire Query DSL.

2. Term frequency: how often the term appears

Term frequency, or TF, measures how often a search term occurs in a given document or field. The basic intuition behind it is simple: a document that contains the search term three times is presumably more relevant for that term than a document that contains it only once. BM25 uses this term frequency as one of the central building blocks of the score, but unlike a naive linear count, the contribution of term frequency saturates as frequency rises.

This saturation is a decisive difference from simpler models: the jump from one to two occurrences raises the score much more than the jump from ten to eleven occurrences. Without this saturation, a document that artificially repeats a search term a hundred times could rank unrealistically high, even though it is no more relevant in content than a document with three natural mentions. BM25 addresses this problem with a nonlinear function that caps the term frequency contribution.

In practice, this means term frequency alone rarely explains why one document gets a higher score than another, once both contain the search term multiple times. The difference between few and very many occurrences is smoothed out by the saturation, which makes BM25 more robust against keyword stuffing than older, purely linear scoring models.


GET /articles/_search
{
  "query": {
    "match": { "content": "elasticsearch" }
  },
  "explain": true
}
// The explain output shows the raw term frequency per document
// and how BM25's saturation function dampens its contribution

3. Inverse document frequency: rarity as a signal

Inverse document frequency, or IDF, measures how rarely a term occurs across the entire document set. Terms that appear in almost every document, like "and" or "the", contribute little to distinguishing between documents and get a low IDF value. Terms that only appear in a few documents, on the other hand, are more meaningful for determining relevance and get a high IDF value.

For a multi-word search query like "waterproof running shoes", this concretely means: if "shoes" appears in many products but "waterproof" only in a few, then a match on "waterproof" contributes more to the overall score than a match on "shoes", because the rarer word carries more distinguishing power. This principle originally comes from the classic TF-IDF model and was adopted and mathematically refined by BM25.

Inverse document frequency is calculated per shard or, by default, across the entire index, depending on the Elasticsearch version and configuration. With strongly imbalanced shards, this can lead to slightly different scores for identical search requests, an effect that is usually negligible in practice but can become visible on very small indices with few shards.

For very small indices where this shard effect actually causes problems, Elasticsearch offers the dfs_query_then_fetch search type, which calculates document frequency globally across all shards before the actual search runs, instead of relying on local shard statistics. This mode is more compute-intensive, but delivers more consistent scores, which can make a noticeable difference especially in small test environments with few documents per shard.


GET /products/_search
{
  "query": {
    "match": { "title": "waterproof running shoes" }
  }
}
// "waterproof" appears in fewer documents than "shoes"
// its higher IDF value gives it more weight in the final score

4. Field length normalization: short vs. long fields

Field length normalization compensates for a systematic effect: longer fields have a statistically higher chance of containing a search term multiple times, simply because they contain more text. Without normalization, long product descriptions would automatically rank better than short, precise titles, even when the short title matches the search term much more directly in content. BM25 compensates for this by evaluating term frequency relative to the average field length across the index.

A document with a short title field that contains the search term once tends to get a higher score contribution than a document with a long description field that contains the same term once, because the relative density of the term is higher in the short field. This effect is one of the reasons a search for an exact product name almost always shows the matching product right at the top, even when other documents also contain the term in longer texts.

This effect is controlled through the b parameter in the BM25 configuration, which determines the strength of field length normalization. A value of 0 disables normalization entirely, a value of 1 applies it fully. The default value in Elasticsearch is 0.75, an empirically proven compromise that delivers good results in most use cases.

5. The BM25 formula in detail

The complete BM25 formula combines term frequency, inverse document frequency, and field length normalization into a single score per term and document, which is then summed across all terms of the search query. Simplified, the formula for a single term looks like this: score = IDF * (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * fieldLength / avgFieldLength)). The constants k1 and b control the saturation of term frequency and the strength of field length normalization respectively.

The numerator of the formula, tf * (k1 + 1), is divided by the denominator, which implements saturation: the higher tf becomes, the closer the fraction approaches the value k1 + 1, without ever reaching it. This asymptotic property is exactly the mathematical implementation of the saturation described in the previous section. The term 1 - b + b * fieldLength / avgFieldLength in the denominator is the field length normalization: for a field longer than average, this term grows and dampens the score, for a shorter field it shrinks and relatively boosts the score.

For a multi-word search query, Elasticsearch computes this score for every term individually and sums the results into the document's overall score. This summation explains why documents containing several search terms tend to rank higher than documents containing only one, regardless of how often the single term occurs.


PUT /products
{
  "settings": {
    "index": {
      "similarity": {
        "custom_bm25": {
          "type": "BM25",
          "k1": 1.2,
          "b": 0.75
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": { "type": "text", "similarity": "custom_bm25" }
    }
  }
}
// k1 controls term frequency saturation, b controls field length normalization
// these defaults match Elasticsearch's out-of-the-box BM25 configuration

6. BM25 versus classic TF-IDF

Before Elasticsearch 5, the classic TF-IDF model was the default scoring algorithm, and BM25 is often described as an "evolution" of TF-IDF. The central difference lies in how term frequency is handled: classic TF-IDF usually applies a square root function to dampen term frequency, while BM25 uses an explicit saturation function with the configurable parameter k1. This difference makes BM25 more controllable and, in practice, more resistant to artificially repeated search terms.

A second important difference concerns field length normalization: classic TF-IDF also accounts for field length, but less explicitly and without the tunable b parameter. BM25 turns the strength of length normalization into an explicit, tunable parameter, which delivers noticeably better results in heterogeneous data sets with strongly varying field lengths, such as short product titles alongside long free-text descriptions.

In practice, the difference between BM25 and TF-IDF shows up most clearly with very frequent search terms: TF-IDF tends to give documents with many repetitions of a term disproportionately high scores, while BM25's stronger saturation mitigates this effect. That is why BM25 has been the default since Elasticsearch 5 and is also used by OpenSearch as the default similarity algorithm.

Property Classic TF-IDF BM25
Term frequency saturation Square root, less controllable Explicit function with parameter k1
Field length normalization Implicit, barely tunable Explicit parameter b, tunable
Behavior under keyword stuffing More prone to disproportionate scores More robust due to stronger saturation
Default since Elasticsearch up to version 4 Elasticsearch from version 5, OpenSearch default

7. Tuning the k1 and b parameters

The BM25 parameters k1 and b can be adjusted at the index level through a custom similarity configuration. k1 controls how quickly term frequency saturates: a higher value allows more repetitions before the score gain flattens out, a lower value flattens the score after only a few repetitions. The default value of 1.2 is a proven starting point that does not need to be adjusted in most use cases.

The b parameter controls the strength of field length normalization, as described in section four. For use cases where field length is not a meaningful signal, such as short, uniform log messages, it can make sense to set b to a lower value or even 0, effectively disabling normalization. Conversely, for data sets with strongly varying field length, a higher b value can improve relevance results.

It is important not to change k1 and b blindly, but to evaluate the changes against concrete test cases with real search queries and expected results. A change to the similarity configuration also requires reindexing, or at least updating the affected fields, since the configuration takes effect at index time.

8. Tracing score calculation with the Explain API

The explain option in the search API is the most important tool for tracing a document's BM25 score. With "explain": true in the search request, Elasticsearch returns, for every hit document, a detailed breakdown of which partial scores come from which terms, including the individual values for term frequency, inverse document frequency, and field length normalization. This breakdown makes visible why a document has a particular score and enables targeted adjustments at the right levers.

Alternatively, the dedicated _explain endpoint delivers the same information for a single document, without having to search through the entire hit list. Both tools are indispensable when relevance problems occur, for instance when a user reports that an obviously matching product does not appear at the top of a search. The explain output then shows exactly which of the three BM25 components is responsible for the lower score.

In practice, it pays off to use the explain output not just occasionally for acute complaints, but to establish it as a fixed part of a relevance testing process. A small set of representative test queries with known, expected top hits can be checked automatically against the explain output after every change to mapping, analyzer, or similarity configuration, so relevance regressions are caught before users notice them.

Mironsoft

Elasticsearch and OpenSearch search solutions for demanding data volumes

Relevant products that don't show up near the top of search?

We analyze your BM25 score with the Explain API, tune k1 and b for your catalog, and fix relevance problems that would otherwise push users to your competitors.

Scoring audit

Trace the BM25 score of real search requests with the Explain API

Parameter tuning

Calibrate k1 and b against concrete test cases for your catalog

Relevance monitoring

Check recurring test cases for search quality after every release

9. Limits of BM25 in practice

BM25 is a purely statistical, lexical scoring model: it knows no meaning, no synonyms, no semantic understanding. A document that contains an exact synonym of the search term but not the term itself gets no score contribution for that term without additional synonym configuration. This limit is often compensated for in modern search systems through additional synonym filters in the analyzer or through supplementary vector search with embeddings, which can capture semantic similarity independent of exact word choice.

A second practical limit concerns business logic: BM25 optimizes purely for textual relevance, not for business goals like margin, stock level, or popularity. These signals have to be brought in through additional mechanisms like the Function Score Query, which combines the pure BM25 score with further factors. BM25 remains the solid textual foundation these boosting mechanisms build on, but it does not replace a complete relevance strategy.

A third limit shows up with very short search requests containing only a single term: here field length normalization has a disproportionately large influence, because even a single additional occurrence strongly changes the relative share of the search term in the field. In such cases it pays off to deliberately lower the b parameter or to stabilize the results with a Function Score Query, so that individual short fields are not disproportionately favored. Despite these limits, BM25 remains the most solid default algorithm available for textual relevance and is rarely fully replaced in practice, usually only deliberately supplemented.

10. Summary

The BM25 algorithm computes the relevance score in Elasticsearch from three components: term frequency, which saturates with increasing repetition, inverse document frequency, which weights rare terms more heavily, and field length normalization, which evaluates short fields fairly against long ones. These three factors are calculated per term and summed across all terms of the search query, controlled by the configurable parameters k1 and b.

Compared to the older TF-IDF model, BM25 offers more controllable saturation and explicit field length normalization, which makes it more robust against keyword stuffing and heterogeneous field lengths. The Explain API remains the central tool for understanding, when relevance problems arise, which of the three BM25 components is responsible for a given score, before turning the parameters or introducing additional boosting mechanisms.

Really understanding BM25, the essentials at a glance

Term frequency

How often a term appears in a document, saturates with increasing repetition, controlled by k1.

Inverse document frequency

Rare terms across the whole index get more weight than common terms.

Field length normalization

Balances short fields against long ones, controlled by the parameter b, default value 0.75.

Explain API

Shows the score breakdown per term, indispensable for relevance debugging.

11. FAQ: BM25 Relevance Scoring

1What does BM25 stand for?
Best Matching 25, the default relevance algorithm of Elasticsearch and OpenSearch.
2What is term frequency in BM25?
How often a term appears, saturates with increasing repetition, controlled by k1.
3What is inverse document frequency?
Measures rarity of a term across the whole index, rare terms get more weight.
4Why do short fields often rank higher?
Due to field length normalization, relative term density is higher in short fields.
5Difference between BM25 and classic TF-IDF?
Explicit, configurable saturation and length normalization instead of implicit and rigid.
6What does k1 do?
Controls how quickly term frequency saturates. Default value 1.2.
7What does b do?
Controls the strength of field length normalization. Default value 0.75.
8How can I trace the score?
With explain: true or the _explain endpoint for the breakdown per term.
9Does BM25 recognize synonyms?
No, purely lexical. Synonyms need analyzer filters or vector search.
10Is BM25 identical in OpenSearch?
Yes, identical formula and identical default parameters as the default similarity.