0

I am making a search query in Elastic Search and I want to treat the fields the same when they match. For example if I search for field field1 and it matches, then the _score is increase by 10(for example), same for the field2.

I was tried function_score but it's not working. It throws an error.

"caused_by": {
    "type": "class_cast_exception",
    "reason": "class 
               org.elasticsearch.index.fielddata.plain.SortedSetDVOrdinalsIndexFieldData 
               cannot be cast to class 
               org.elasticsearch.index.fielddata.IndexNumericFieldData 
               (org.elasticsearch.index.fielddata.plain.SortedSetDVOrdinalsIndexFieldData 
               and org.elasticsearch.index.fielddata.IndexNumericFieldData are in unnamed 
               module of loader 'app')"
}

The query:

{
  "track_total_hits": true,
  "size": 50,
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "field1": {
                  "value": "Value 1"
                }
              }
            },
            {
              "term": {
                "field2": {
                  "value": "value 2"
                }
              }
            }
          ]
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "field1",
            "factor": 10,
            "missing": 0
          }
        },
        {
          "field_value_factor": {
            "field": "field2",
            "factor": 10,
            "missing": 0
          }
        }
      ],
      "boost_mode": "multiply"
    }
  }
}
Valentin
  • 1,159
  • 1
  • 11
  • 22

2 Answers2

0

You can use function score with filter function to boost.

assuming that your mapping looks like the one below

{
  "mappings": {
    "properties": {
      "field_1": {
        "type": "keyword"
      },
      "field_2": {
        "type": "keyword"
      }
    }
  }
}

with documents

{"index":{}}
{"field_1": "foo", "field_2": "bar"}
{"index":{}}
{"field_1": "foo", "field_2": "foo"}
{"index":{}}
{"field_1": "bar", "field_2": "bar"}

you can use weight parameter to boost the documents matched for each query.

{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "filter": {
            "term": {
              "field_1": "foo"
            }
          },
          "weight": 10
        },
        {
          "filter": {
            "term": {
              "field_2": "foo"
            }
          },
          "weight": 20
        }
      ],
      "score_mode": "multiply"
    }
  }
}
pakio
  • 26
  • 2
  • As much as I read, the weight multiply the score of a certain match, so even if the weights are equal, the score could still be different and what I want is to set the scores equal. I am wrong? – Valentin Oct 31 '22 at 13:03
  • 1
    that happens if you use the boost parameter[1] in the must query. The key point of the query that I posted is unlike the must query calculates the score for each query, the filter query returns the constant score(1.0) whatever the query inside it is. [2] So the query will return the same score if the weight is the same. *1: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html *2: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html#query-dsl-bool-query – pakio Nov 01 '22 at 03:32
0

You can refer below solution if you want to provide manual weight for different field in query. This will always replace highest weight field on top of your query response -

Elasticsearch query different fields with different weight

Sourabh_K
  • 56
  • 2