Rank text matches
The language tabs use earlier client interfaces. Check SDK versions and connection setup before running them.
BM25 ranks documents using term frequency and document length. Use it to see stronger text matches first.
Before you run it: Scores from different queries are not directly comparable. Highlight, facet and fuzzy options apply to the documented BM25 path.
The one-document sample is enough to check that p001 is found. Add other documents before judging ranking. A BM25 score describes how strongly the query words match relative to other indexed documents; it is not a percentage confidence that an answer is correct.
- Index searchable textBuild the sample field's term statistics.
- Run the ranked queryRequest BM25 with the desired result limit.
- Read highest scores firstInspect the matching IDs and available stored text.
Follow the example
- Index documents and any stored text needed for highlights.
- Set mode: bm25 explicitly.
- Choose a maximum result count.
- Read the hits in score order.
Run the request
First index the sample text. Use the same table and field in the search request; storing a row alone does not create its search entry.
curl -G "https://$OC_HOST/v1/tenants/$OC_TENANT/fts/shop.products/description" \
-H "Authorization: Bearer $OC_TOKEN" \
--data-urlencode "q=wireless headphones" \
--data-urlencode "mode=bm25" \
--data-urlencode "k=10"Check the result
Higher scores rank first for this query. Highlights or facets change the response to an object with hits and facets.
[
{ "doc_id": "p001", "score": 9.42 },
{ "doc_id": "p027", "score": 7.18 },
{ "doc_id": "p014", "score": 4.55 }
]A bare array of { doc_id, score } objects - no { "mode": ..., "hits": [...] } wrapper.
Read highlighted or faceted results
The plain bare-array shape only changes when you add highlight=true or facets=. Then - and only then - BM25 returns an object with a hits array (each hit carrying optional highlights) and a facets block. Highlights require the doc text to have been stored via POST /fts/:t/:f/doc first.
{
"hits": [
{
"doc_id": "p001",
"score": 9.42,
"highlights": {
"description": ["Over-ear <em>wireless</em> <em>headphones</em> with…"]
}
},
{ "doc_id": "p027", "score": 7.18, "highlights": {} }
],
"facets": {
"category": [{ "value": "electronics", "count": 2 }]
}
}k, fuzzy, highlight, facets, and explain are BM25-only - they are silently ignored in boolean and phrase modes.
Understand the behavior
- The query is tokenised, then for each token the engine fetches the posting list along with term frequencies and document lengths.
- Each candidate document gets a BM25 score using the Lucene defaults:
k1 = 1.2,b = 0.75. Score grows with how often the rare terms appear and shrinks if the document is much longer than average. - A top-
kheap keeps the highest scorers; everything else is discarded.
Optional query params: fuzzy=1 for single-character typo tolerance, highlight=true to return matched-snippet text, facets=col,col for grouped counts alongside hits.
Important limits and checks
- Comparing scores across queries. A BM25 score of 9.4 means nothing on its own and can't be compared to the 9.4 from a different query. Use scores to rank within one result set only.
- Forgetting
k. If you omit it, you get a default cap. Setkto what you actually need; ranking the entire corpus is wasted work. - Reaching for BM25 when boolean would do. If you only need "does it match", boolean is cheaper and the answer is the same set.