5

I have the following type in elasticsearch

"hotel" : {
   "magicScore" : 1
   "rooms" : [
        {
       "type" : "single",
       "magicScore" : 1
        }, 
        {
        "type" : "double",
        "magicScore" : 2
        }
    ]
}

where rooms is of type nested. I would like to sort using a scripted sort, for example

 "sort" : [ {
    "_script" : {
      "script" : "return doc['magicScore'].value + doc['rooms.magicScore'].value",
       "params" :  ,
      "type" : "number",
      "reverse" : true
    }
  } ]

This does not work because rooms are nested objects, is there a way around this?

2 Answers 2

3

Elasticsearch allows Script Based Sorting and Sorting within nested objects, more over you can mix both approaches together. You could try something like:

"sort" : [ {
   "_script" : {
      "nested": {
         "path": "rooms"
      },
      "script" : "return doc['magicScore'].value + doc['rooms.magicScore'].value",
      "params" :  ,
      "type" : "number",
      "reverse" : true
}}]

Once the nested path is specified, elasticsearch would lookup the terms of referred nested documents if those are indexed, so it would be possible to refer to them through the doc map. This would avoid the need to load the whole _source.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm facing similar problem but while trying to sort using the script, I'm getting RequestError: RequestError(400, u'x_content_parse_exception', u'[1:29] [_script] failed to parse field [type]')
This answer absolutely deserves an upvote!
2

As per the documentation:

doc[...] notation only allows for simple valued fields (can’t return a json object from it) and makes sense only on non-analyzed or single term based fields.

You would need to use access it via the _source field

Something on these lines:

   "sort": [
      {
         "_script": {
            "script": "m=doc['magicScore'].value;for(obj in _source.rooms){ m += obj.magicScore;};return m;",
            "type": "number",
            "reverse": true
         }
      }
   ]

2 Comments

hey, sorry for taking a while to reply. What you wrote works and ill accept it as answer. I had a huge performance hit because my documents are large. I ended up using a function_score query in java it would be something like QueryBuilders .nestedQuery("rooms", QueryBuilders.functionScoreQuery(filterBuilder, ScoreFunctionBuilders.scriptFunction() .param("values", values)) ).scoreMode("max")
The next step for a future refactoring would be to use a bool query so i can access both the fields from the parent object and the nested object. The functionscorequery inside the nestedquery can only see fields from the nested documents. I had to put the magicScore field inside the nested documents for the whole thing to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.