9

There is a field where there is an array stored. I want to sort the documents based on the array length of that field.

Sample documents

document 1 = {
"countryCodes" : ["US","UK","UA","IN"]
}

document 2 ={
"countryCodes" : ["FR","SU","UG","UK","US"]
}

So, up on sort, the results should be showing document 2 first and then document 1.

5 Answers 5

7

There are two options here.

  1. Use token count type as multi field in the mapping - This way another field would be stored as mutlti field which has the length of the array . You can learn more about it here.
  2. Scripting - The same can be achieved using scripting too .

    { "sort": { "_script": { "script": "doc['countryCodes'].values.size()" } } }

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

Comments

4

For Elasticsearch 5.6.7 query should look like this:

GET index/_search
{
    "query": {
        "match_all": {}
    },
    "sort": {
        "_script": {
            "type" : "number",
            "script" : {
                "lang": "painless",
                "source": "doc.countryCodes.values.size()"
            },
            "order" : "desc"
        }
    }
}

Comments

2

The easiest way to do this would be to also index another field containing the length of the array and then sort on that field.

Another way would be to use script-based sorting and return the length of the array using groovy.

{
  "query": {
    "match_all": {}
  },
  "sort": {
    "_script": {
      "script": "doc.countryCodes.values.size()"
    }
  }
}

Also make sure to enable dynamic scripting in order for this to work.

Comments

2

For Elasticsearch 6.8 the query should look like this:

{
   "query": {
      "match_all": {}
   },
   "sort": {
      "_script": {
         "type": "number",
         "script": "doc.countryCodes.size()",
         "order": "desc"
      }
   }
}

Comments

2

For Elasticsearch 7.6, the only thing that worked for me was a combination of Kamel Mili's answer and Vineeth Mohan's answer:

POST /test/_search
{
  "sort": {
    "_script": {
      "type": "number",
      "script": "doc['countryCodes'].size()",
      "order": "desc"
    }
  },
  "query": {
    "match_all": {}
  }
}

If countryCodes is a regular text field, you'll need

      "script": "doc['countryCodes.keyword'].size()",

instead.

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.