2
votes

Is it possible to change the sorting of results of a Range Aggregation in elasticsearch? I have a keyed Range query in elasticsearch and want to sort according to keys instead of doc_count.

My documents are:

POST /docs/doc/1
{
    "price": 12
}

POST /docs/doc/2
{
    "price": 8
}

POST /docs/doc/3
{
    "price": 15
}

And the aggregation query:

POST /docs/_search
{
   "size": 0,
   "aggs": {
      "price_ranges": {
         "range": {
            "field": "price",
            "keyed": true,
            "ranges": [
               {
                  "key": "all",
                  "from": 0
               },
               {
                  "key": "to10",
                  "from": 0,
                  "to": 10
               },
               {
                  "key": "from11",
                  "from": 11
               }
            ]
         }
      }
   }
}

The result for this query is:

"aggregations": {
   "price_ranges": {
      "buckets": {
         "to10": {
            "from": 0,
            "from_as_string": "0.0",
            "to": 10,
            "to_as_string": "10.0",
            "doc_count": 2
         },
         "all": {
            "from": 0,
            "from_as_string": "0.0",
            "doc_count": 4
         },
         "from11": {
            "from": 11,
            "from_as_string": "11.0",
            "doc_count": 2
         }
      }
   }
}

I'd like to sort the results according to the key, not according to range value. According to elasticsearch documentation it is not possible to specify a sort order and When specifying a sort order I get the following exception:

"reason": "Unknown key for a START_ARRAY in [price_ranges]: [order]."

Any ideas on how to cope with this? Thanks!

2
The issue is that when keyed is true, the result is returned as a hash which is unordered by definition, to the contrary of an array which is ordered. Have you tried to configure "all" with "from": -1, maybe it'll come up first? - Val
There doesn't seem to be a way to do this for range aggregations. I think the best way to cope with this is to sort the buckets in the client. - Jeremy

2 Answers

2
votes

Since the keys seem to be ordered according to ascending values of the from value, you can "cheat" a little bit and modify the from value of the all bucket to -1, then the all bucket will appear first, then to10 and finally from11:

POST /docs/_search
{
   "size": 0,
   "aggs": {
      "price_ranges": {
         "range": {
            "field": "price",
            "keyed": true,
            "ranges": [
               {
                  "key": "all",
                  "from": -1
               },
               {
                  "key": "to10",
                  "from": 0,
                  "to": 10
               },
               {
                  "key": "from11",
                  "from": 11
               }
            ]
         }
      }
   }
}
0
votes

In general you can use a bucket_sort aggregation. Then you can sort by _key, _count or a sub-aggregation (i.e. by a metric calculated for each bucket).

Given that you only have three fixed buckets though, I would simply do the sorting on the client-side instead.