Script score query with field value factor from an array of objects

Hi,

I am trying to score the returned documents of a term query based on a score from the term object that was hit.

Let me explain with examples.
Suppose this is my index mapping:

"documents" : {
  "mappings" : {
     "tags" : {
       "properties" : {
         "tag" : {
           "type" : "keyword"
         },
         "score" : {
           "type" : "double"
         }
       }
     }
   }
}

I want to be able to do a term query like this:

GET documents/_search
{
  "query": {
    "term": {
      "tags.tag": {
         "value": "TAG1"
       }
    }
  }
}

and influence the scoring of the document based on the score value in the "score" field in the tags object that got hit when returning the document.

I was able to achieve this with the following script score, but it is very slow, since I there could be many tags and many documents.

GET documents/_search
{
  "query": {
    "function_score": {
      "query": {
        "term": {
          "tags.tag": {
            "value": "TAG1"
          }
        }
      },
      "script_score": {
        "script": {
          "lang": "painless", 
          "params": {
            "tag": "TAG1"
          }, 
          "source": """
              def tag = params._source.tags.stream().filter(e -> e.tag.equals(params.tag)).findAny().orElse(0);
              return Math.log(2+tag.score);
           """
        }
      }
    }
  }
}

The problem is that I have to find the tag object containing the score in the script to use this score.
I was thinking to create an object which will be a mapping from tag to score, which can be accessed directly to return the score.
However, this is not possible without dynamic mapping, and dynamic mapping is very expensive, since there can be hundreds and thousands of tags in a single document.
Does anybody have a suggestion of how can I use script score without having to iterate to the list to find the score I am looking for.

Thank you!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.