Elasticsearch Normalised Score with Boost Documents

Viewed 10

I am building a query that takes a set of codes and geo_point locations. The result should be a list of documents ordered by distance to origin. However, I would like to be normalised with let say a score of 10 for the document in the origin location and decreasing according to distance from origin. I have actually managed to build this search but I also would like to increase the score of a document if this includes an additional variable in the list of codes.

These are the requirements:

  • The output should be a list of documents which score is normalised according to distance from origin.
  • Documents returned should contain at least one yvar (i.e. yvar1 OR yvar2 OR yvar3 OR yvar...).
  • Only documents after a certain date should be returned
  • Only documents containing all the xvars passed to the query must be returned.
  • If a document has an additional x variable (e.g xvar4) the score for this document, should be increased by 0.1. This is the bit I am struggling with.

This is my mapping:

{
  "mappings": {
    "properties": {
      "codes": {
        "type": "keyword"
      },
      "date": {
        "type": "date",
        "format": "dd/MM/yyyy"
      },
      "coordinates": {"type": "geo_point"}
    }
  }
}

Some example documents (NB: The distanceToOrigin is for analysing the output only):

{ "create" : { "_index": "my-index", "_id" : "1" } }
{ "id": 1,  "coordinates": { "lat": 51.5132, "lon": -0.1362}, "available capacity": 5, "last updated": "01/11/2021", "ResponseCodes": ["xvar1", "xvar2", "xvar3", "yvar1", "yvar2", "yvar3" ] ,"distanceTOorigin": 0 }
{ "create" : { "_index": "my-index", "_id" : "2" } }
{ "id": 2,  "coordinates": { "lat": 52.9114, "lon": 0.5580}, "available capacity": 5, "last updated": "01/11/2021", "ResponseCodes": ["xvar1", "xvar2", "xvar3", "xvar4", "yvar1", "yvar2", "yvar3" ] ,"distanceTOorigin": 114 }
{ "create" : { "_index": "my-index", "_id" : "3" } }
{ "id": 3,  "coordinates": { "lat": 51.4890, "lon": -0.6029}, "available capacity": 5, "last updated": "01/11/2021", "ResponseCodes": ["xvar1", "xvar2", "xvar3", "yvar1", "yvar2", "yvar3" ] ,"distanceTOorigin": 22 }
{ "create" : { "_index": "my-index", "_id" : "4" } }
{ "id": 4,  "coordinates": { "lat": 57.2555, "lon": -3.2692}, "available capacity": 5, "last updated": "01/11/2021", "ResponseCodes": ["xvar1", "xvar2", "xvar3", "yvar1", "yvar2", "yvar3" ] ,"distanceTOorigin": 530 }

My query which produces a normalised list of documents:

{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "boost": "1", 
      "functions": [
        {
          "filter": [
            { "range": { "date":{ "gte": "01/11/2000" }}},
            { "terms_set": { "codes" : { "terms" : ["yvar1", "yvar2", "yvar3" ],
                "minimum_should_match_script": { "source": "1" }}}}
          ],
          "random_score": {}, 
          "weight": 1
        },
        {
          "filter": [
            { "terms_set": { "codes" : { "terms" : ["xvar1", "xvar2", "xvar3" ],
                "minimum_should_match_script": { "source": "params.num_terms" }}}}
          ],
          "weight": 1
        },

        {
          "exp": {
            "coordinates": {
              "origin": "51.5132, -0.1362",
              "offset": "0km",
              "decay": 0.5,
              "scale":"350km"}
            },
            "weight": 10
        }
        
      ],    
      "max_boost": 10,
      "score_mode": "max",
      "boost_mode": "multiply" 
    }
  }
}

This is what I tried as a query (substituting the match_all query) but does not work as I end up with a non-normalised list

  "query": {
    "bool": {
       "should": [
          {
            "terms_set": { "codes" : { "terms" : ["xvar4"],
                "minimum_should_match_script": { "source": "0" }, "boost" : 0.1}}
          },
          {
             "match_all": {}
          }
       ]
    }
 }

Any help for this ealsticsearch beginner will be greatly appreciated.

1 Answers

I found the solution by accessing the _score in a script_score query:

{
  "query": {
    "script_score": {
      "query": {
        "match": { "codes": "xvar4" }
      },
      "script": {
        "source": "_score +0.1"
      }
    }
  }
}
Related