Function Score Query, using Field Value Factor — ElasticSearch

André Coelho
5 min readMay 4, 2022

--

The Query Function Score is one of the ways we can manipulate the score of documents.

Through the Query Function Score it will be possible to apply functions that will help us to increase or decrease the scores of documents.

Let’s talk about the predefined functions supported by Function Score:

  • weight: Apply a single enlargement to each document without the enlargement being normalized.
  • field_value_factor: Use the value of a field in the document to change the _score.
  • random_score: Use consistent random score to rank results differently for each user.
  • decay functions: Score a document with a function that decays depending on the distance of a numeric field value in the document from a user-determined source.
  • script_score: Use a custom script to take full control of the scoring logic.

Now let’s talk about some important parameters:

  • max_boost: limit the maximum effect the function can have.
  • score_mode: Combines the result of the used functions. Score mode has the following parameters:
    - multiply: Function results are multiplied together (default).
    - sum: Function results are added up.
    - avg: The average of all the function results.
    - max: The highest function result is used.
    - min: The lowest function result is used.
    - first: Uses only the result from the first function that either doesn’t have a filter or that has a filter matching the document.
  • boost_mode: Combines the _score result of the query with the _score of the functions. Boost mode accepts the following parameters:
    - multiply: Multiply the _score with the function result.
    - sum: Add the function result to the _score.
    - min: The lower of the _score and the function result
    - max: The higher of the _score and the function result.
    - replace: Replace the _score with the function result

In this post we will work with the field_value_factor. Let’s manipulate the score of documents from a field. The field will be the rating, this index is the same one created in this post.

To use the field_value_factor we must understand some of its parameters:

  • field: document field.
  • factor: value by which to multiply the field value. The default is 1.
  • modifier: Modifier to apply to the field value, can be one of: none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, or reciprocal. See more.
  • missing: value if the document does not have the specified field.

Let’s run a query that returns all movies without any criteria.

GET idx_movies/_search
{
"_source": [
"title",
"rating",
"metascore"
],
"query": {
"match_all": {}
}
}

Note that the order of results is not taking into account the highest rating.

"hits" : [
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "YxQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 8.1,
"metascore" : 76,
"title" : "Guardians of the Galaxy"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "ZBQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 7,
"metascore" : 65,
"title" : "Prometheus"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "ZRQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 7.3,
"metascore" : 62,
"title" : "Split"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "ZhQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 7.2,
"metascore" : 59,
"title" : "Sing"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "ZxQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 6.2,
"metascore" : 40,
"title" : "Suicide Squad"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "aBQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 6.1,
"metascore" : 42,
"title" : "The Great Wall"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "aRQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 8.3,
"metascore" : 93,
"title" : "La La Land"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "ahQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 6.4,
"metascore" : 71,
"title" : "Mindhorn"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "axQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 7.1,
"metascore" : 78,
"title" : "The Lost City of Z"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "bBQCi4ABHFVsAeBmxoOC",
"_score" : 1.0,
"_source" : {
"rating" : 7,
"metascore" : 41,
"title" : "Passengers"
}
}
]

Now let’s apply the function score and use the field_value_factor where the factor will be 5. That way the function score will be rating * 5.

GET idx_movies/_search
{
"_source": ["title", "rating", "metascore"],
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"field_value_factor": {
"field": "rating",
"factor": 5,
"missing": 0,
"modifier": "none"
}
}
],
"boost_mode": "replace",
"score_mode": "sum"
}
}
}

Note that I also chose to overwrite the query’s _score with the function’s score.
The movie The Dark Knight rated 9 will have _score 45 as it is the result of 5 * 9.

"hits" : [
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "mRQCi4ABHFVsAeBmxoOD",
"_score" : 45.0,
"_source" : {
"rating" : 9,
"metascore" : 82,
"title" : "The Dark Knight"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "sxQCi4ABHFVsAeBmxoOE",
"_score" : 44.0,
"_source" : {
"rating" : 8.8,
"metascore" : 74,
"title" : "Inception"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "2BQCi4ABHFVsAeBmxoOF",
"_score" : 44.0,
"_source" : {
"rating" : 8.8,
"metascore" : "",
"title" : "Dangal"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "hxQCi4ABHFVsAeBmxoOD",
"_score" : 43.0,
"_source" : {
"rating" : 8.6,
"metascore" : 74,
"title" : "Interstellar"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "wxQCi4ABHFVsAeBmxoOE",
"_score" : 43.0,
"_source" : {
"rating" : 8.6,
"metascore" : 79,
"title" : "Kimi no na wa"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "XBQCi4ABHFVsAeBmxoSH",
"_score" : 43.0,
"_source" : {
"rating" : 8.6,
"metascore" : 57,
"title" : "The Intouchables"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "oxQCi4ABHFVsAeBmxoOE",
"_score" : 42.5,
"_source" : {
"rating" : 8.5,
"metascore" : 66,
"title" : "The Prestige"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "xhQCi4ABHFVsAeBmxoOE",
"_score" : 42.5,
"_source" : {
"rating" : 8.5,
"metascore" : 85,
"title" : "The Departed"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "3xQCi4ABHFVsAeBmxoOF",
"_score" : 42.5,
"_source" : {
"rating" : 8.5,
"metascore" : 78,
"title" : "The Dark Knight Rises"
}
},
{
"_index" : "idx_movies",
"_type" : "_doc",
"_id" : "6BQCi4ABHFVsAeBmxoOF",
"_score" : 42.5,
"_source" : {
"rating" : 8.5,
"metascore" : 88,
"title" : "Whiplash"
}
}
]

The Query Function Score has several applications and what we saw here is the use of one of its functions. Read the documentation and try to tailor Function Score usage according to your requirements.

--

--

André Coelho

Developer of web and mobile systems. Enthusiast in the area of ​​automation and electronics and I have hobbie music.