skip to Main Content

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"
    }
  }
}

2

Answers


  1. 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"
        }
      }
    }
    
    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search