How to access doc values of a nested array inside a script?


(Bruno Miranda) #1

I am using Elasticsearch 1.7

Given the following index, how would I select proper item in the nested array and access one of it's values? The purpose here is to use it inside the value inside a script_score.

# Create mapping
curl -XPUT localhost:9200/test/user/_mapping -d '
{
  "user" : {
    "properties" : {
      "name" : {
        "type" : "string"
      },
      "skills" : {
        "type": "nested", 
        "properties" : {
          "skill_id" : {
            "type" : "integer"
          },
          "recommendations_count" : {
            "type" : "integer"
          },
        }
      }
    }
  }
}
'

Let's index some data.

curl -XPUT localhost:9200/test/user/1 -d '
{
   "name": "John",
   "skills": [
      {
         "skill_id": 100
         "recommendations_count": 5
      },
      {
         "skill_id": 200
         "recommendations_count": 3
      }
   ]
}
'

curl -XPUT localhost:9200/test/user/1 -d '
{
   "name": "Mary",
   "skills": [
      {
         "skill_id": 100
         "recommendations_count": 9
      },
      {
         "skill_id": 200
         "recommendations_count": 0
      }
   ]
}
'

My query filters by skill_id and this works well. I then want to be able to use script_score to boost the score of the user documents with a higher recommendations_count for the given skill_id. (<-- this is key).

curl -XPOST localhost:9200/test/user/_search -d '
{      
    "query":{
      "function_score":{
        "query":{
          "bool":{
            "must":{
              "nested":{
                "path":"skills",
                "query":{
                  "bool":{
                    "must":{
                      "term":{
                        "skill_id":100
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "functions":[
          {
            "script_score": {
               "script": "sqrt(1.2 * doc['skills.recommendations_count'].value)"   
            }
          }            
        ]
      }
    }
  }
} 

How do I access the skills array from within the script, find the 'skill_id: 100' item in the array, and then use its recommendations_count value? The script_score above doesn't currently work (score is always 0 regardless of the data, so I assume doc['skills.recommendations_count'].value is not looking in the right place.


(vivek) #2

Any luck on this issue? Facing a similar issue in terms of accessing array from with in the script.


(brupm) #3

No, what I did is use field-value-factor instead: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-field-value-factor - then you can get the value from the nested attribute easily:

json.query do
  # Take the recommendations_count from that skill
  json.function_score do
    json.field_value_factor do
      json.field 'skills.recommendations_count'
    end
  end
end

(vivek) #4

Thanks for the reply @brupm.

Could you pl give us the exact query that you used for your usecase with field_vlaue_factor for full clarity on syntax which is where we end up spending lot of time. We are looking for snippet of function_score which embeds the above logic that you have given.


(system) #5