Custom Scoring in Elasticsearch Using function_score
Elasticsearch calculates a relevance score for each document, but using the function_score query you can customize this scoring by combining the original query_score with a user-defined func_score through various functions such as weight, random_score, field_value_factor, decay_function, and script_score, allowing flexible ranking based on business needs.
Elasticsearch assigns a relevance score to each document matching a query and returns results sorted by this score. In many scenarios you need to re‑rank results based on additional criteria such as freshness, distance, or popularity.
Custom Scoring Process
The function_score query lets you replace the default query_score with a new result_score calculated as query_score combined with a custom func_score . The combination method is defined by the boost_mode parameter (default is multiply ).
Steps:
Execute the original query and obtain query_score for each document.
Run the custom scoring function(s) to produce func_score for each document.
Combine query_score and func_score according to boost_mode (e.g., multiply) to get result_score .
Example without custom scoring:
GET /_search {
"query": { "match": { "title": "elasticsearch" } }
}Assume three hits have original scores 0.3 , 0.2 , 0.1 . Using a simple function_score with a weight of 5:
GET /_search {
"query": {
"function_score": {
"query": { "match": { "message": "elasticsearch" } },
"weight": 5
}
}
}The final scores become 0.3*5 = 1.5 , 0.2*5 = 1.0 , 0.1*5 = 0.5 , and results are sorted by these values.
function_score Scoring Functions
The function_score query supports several built‑in functions:
weight : assign a static weight.
random_score : generate a random value in [0,1) , optionally with a seed and field to keep randomness consistent per user.
field_value_factor : use a numeric field value, optionally applying a factor , modifier , and missing value.
decay_function (gauss, linear, exp): decay scores based on distance from an origin (numeric, date, or geo‑point).
script_score : provide a custom painless script.
Weight Example
{
"query": {
"function_score": {
"query": { "match": { "message": "elasticsearch" } },
"weight": 5
}
}
}Random Score with Seed
{
"query": {
"function_score": {
"random_score": { "seed": 10, "field": "_seq_no" }
}
}
}When multiple functions are combined, you can control how they are merged using score_mode (e.g., multiply , sum , avg , max , min ) and limit the final boost with max_boost . Low‑scoring documents can be filtered out with min_score .
Field Value Factor Example
{
"query": {
"function_score": {
"query": { "match": { "message": "elasticsearch" } },
"field_value_factor": {
"field": "likes",
"factor": 1.2,
"missing": 1,
"modifier": "log1p"
}
}
}
}This multiplies the original score by log1p(1.2 * likes) , boosting documents with more likes.
Decay Function Example (Gaussian)
{
"query": {
"function_score": {
"query": { "match_all": {} },
"gauss": {
"@timestamp": {
"origin": "2013-09-17",
"scale": "10d",
"offset": "5d",
"decay": 0.5
}
}
}
}
}Documents within 5‑15 days of the origin keep full weight; beyond that the score decays to 0.5.
Script Score Example
{
"query": {
"function_score": {
"query": { "match": { "message": "elasticsearch" } },
"script_score": {
"script": {
"source": "Math.log(2 + doc['my-int'].value)"
}
}
}
}
}Custom scripts can reference document fields via doc['field'].value and use any painless expression.
Conclusion
Understanding Elasticsearch's custom scoring capabilities enables you to build sophisticated, business‑driven ranking strategies that go beyond the default relevance algorithm.
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.