# Sorting on a scripted terms aggregation is lexically instead of numerically

**URL:** <https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256>\
**Category:** Elasticsearch\
**Created:** [September 26, 2025, 3:14pm UTC](https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256 "2025-09-26T15:14:38Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![spinscale](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/spinscale/32/25011_2.png) [@spinscale](https://discuss.elastic.co/u/spinscale)\
**Post date:** [September 26, 2025, 3:14pm UTC](https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256/1 "2025-09-26T15:14:38Z")

</div>

Hey,

maybe this is intended behaviour but I would like to verify. If I am using a terms aggregation with a script and specify sorting by key, it does not take into account when the script is returning an integer value. Example:

```auto
PUT test 

PUT test/_bulk?refresh
{ "index" : {} }
{ "date" : "2025-09-26T01:23:45.00Z" }
{ "index" : {} }
{ "date" : "2025-09-26T02:23:45.00Z" }
{ "index" : {} }
{ "date" : "2025-09-26T10:23:45.00Z" }
{ "index" : {} }
{ "date" : "2025-09-26T10:23:45.00Z" }

GET test/_search
{
  "size": 0,
  "aggs": {
    "by_hour": {
      "terms": {
        "order": {
          "_key": "asc"
        },
        "script": {
          "source": "doc['date'].value.getHour()"
        }
      }
    }
  }
}

```

This returns

```auto
"aggregations": {
    "by_hour": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "1",
          "doc_count": 1
        },
        {
          "key": "10",
          "doc_count": 2
        },
        {
          "key": "2",
          "doc_count": 1
        }
      ]
    }
  }

```

The [docs](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-terms-aggregation#_ordering_by_the_term_value) state:

> In this case, the buckets are ordered by the actual term values, such as lexicographic order for keywords or numerically for numbers.

Running the script with `Debug.explain()` returns an Integer as value.

Sort order is also correct when I index a field as an integer value and use that with the order in a terms aggregation.

This is on Elasticsearch 9.1.3

Is this a scripting issue or am I holding it wrong?

–Alex

---

<div class="post-metadata">

**Author:** ![Ignacio\_Vera](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ignacio_vera/32/36674_2.png) [@Ignacio\_Vera](https://discuss.elastic.co/u/Ignacio_Vera)\
**Post date:** [September 26, 2025, 3:20pm UTC](https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256/2 "2025-09-26T15:20:04Z")

</div>

Can you use a runtime field instead where you have more control of the data type?

I can see the keys of the aggregation are strings so they seem to be treated as strings.

---

<div class="post-metadata">

**Author:** ![spinscale](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/spinscale/32/25011_2.png) [@spinscale](https://discuss.elastic.co/u/spinscale)\
**Post date:** [September 26, 2025, 4:02pm UTC](https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256/3 "2025-09-26T16:02:56Z")

</div>

That works. Should I file a bug for the script or is this considered deprecated?

---

<div class="post-metadata">

**Author:** ![Ignacio\_Vera](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ignacio_vera/32/36674_2.png) [@Ignacio\_Vera](https://discuss.elastic.co/u/Ignacio_Vera)\
**Post date:** [September 28, 2025, 10:10am UTC](https://discuss.elastic.co/t/sorting-on-a-scripted-terms-aggregation-is-lexically-instead-of-numerically/382256/4 "2025-09-28T10:10:25Z")

</div>

Thanks Alex!

It sounds to me like a bug because there is a discrepancy between what is reported in `Debug.explain()` and what is returned. Please file a bug if you have time.
