6

I am using Elasticsearch 5.5 and have an index with such mapping:

{
  "my_index": {
    "mappings": {
      "my_type": {
        "properties": {
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "my_array": {
            "properties": {
              "array": {
                "type": "float"
              },
              "length": {
                "type": "long"
              }
            }
          }
        }
      }
    }
  }
}

I would like to search by title and sort by first value from array. Also it would be great to set this first value to the _score field. So, I've prepared such request:

GET my_index/my_type/_search
{
    "query": {
      "term": {
        "title.keyword": "Shorts"
      }
    }, 
    "sort" : {
        "_script" : {
            "type" : "number",
            "script" : {
                "lang": "painless",
                "inline": "doc['my_array.array'][0]"
            },
            "order" : "asc"
        }
    }
}

Unfortunately it doesn't work. I feel something is missing or wrong.

6
  • What error does it give? Commented Oct 30, 2017 at 12:28
  • @HatimStovewala There is no error, but the order is wrong Commented Oct 30, 2017 at 13:28
  • May you please provide some example documents and the response? What do you expect to be in the response and what is there actually? Thank you. Commented Oct 30, 2017 at 19:16
  • @NikolayVasiliev With such request: GET my_index/my_type/_search { "sort" : { "_script" : { "type" : "number", "script" : { "lang": "painless", "inline": "doc['embeddings.array'][0]" }, "order" : "asc" } } } The response is jsonblob.com/05e5893a-be1c-11e7-9ae8-cdd8d94a615d Commented Oct 31, 2017 at 9:16
  • Does this valid way to access first element of array doc['my_array.array'][0] ? Commented Oct 31, 2017 at 11:13

2 Answers 2

4

The correct way of using that Painless script is like this:

{
  "query": {
    "term": {
      "title.keyword": "Shorts"
    }
  },
  "sort": {
    "_script": {
      "type": "number",
      "script": {
        "lang": "painless",
        "inline": "params._source.my_array.array[0]"
      },
      "order": "asc"
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

1

As Andrei pointed out in his answer, you should refer directly to _source in your painless script.

This happens because in the Lucene index (which is what ElasticSearch is built upon) does not have a notion of original order of the values in your array. Moreover, arrays do not work as you would expect:

Arrays of objects do not work as you would expect: you cannot query each object independently of the other objects in the array.

Basically, you are sorting by a random number from your list.

What Andrei is suggesting is to use the _source, which is, to read the original JSON document, parse it and extract the needed value from there (it will work). But _source is slow (because instead of accessing fast index you read from the disk, every time, every document).

You have 2 other options:

  • move this first element as a separate field;
  • use nested data type and explicitly define order.

Hope that helps!

Comments

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.