michael lother
michael lother

Reputation: 139

Sort based on length of an array in elasticsearch

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.

Upvotes: 9

Views: 7293

Answers (5)

Glorfindel
Glorfindel

Reputation: 22641

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.

Upvotes: 1

Kamel Mili
Kamel Mili

Reputation: 1434

For Elasticsearch 6.8 the query should look like this:

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

Upvotes: 2

Luka Lopusina
Luka Lopusina

Reputation: 2647

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"
        }
    }
}

Upvotes: 4

Vineeth Mohan
Vineeth Mohan

Reputation: 19253

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()" } } }

Upvotes: 7

Val
Val

Reputation: 217314

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.

Upvotes: 2

Related Questions