Elasticsearch Java API客户端将聚合键作为字符串返回,而不是数字

后端开发 2026-07-10

我正在使用Elasticsearch Java API Client来执行带聚合的查询。

在Elasticsearch中,我的字段映射是:

"departmentId": {
  "type": "integer"
}

我的聚合查询是在该字段上的terms聚合。


预期行为

从Elasticsearch的响应(原始JSON),我期望得到:

"key": 1

(即数值)


实际行为(Java客户端)

使用:

SearchResponse<JsonData> response = esClient.search(request, JsonData.class);

甚至:

SearchResponse<Map> response = esClient.search(request, Map.class);

我得到:

"key": "1"

(即字符串而不是数字)


观察

  • 这个问题仅在 聚合 中出现,而不是在 _source
  • 我对Java客户端进行了调试,发现:

  • 聚合的解析使用 TypedKeysDeserializer

  • 桶键(bucket keys)的反序列化使用 JsonpDeserializer.STRING
  • 内部,它会调用:

    parser.getString() +这接收 VALUE_NUMBER 并将其转换为字符串


问题

  1. 这是Elasticsearch Java API Client的预期行为吗?
  2. 有没有办法配置客户端将聚合键返回为数值类型而不是字符串?
  3. 还是手动转换是唯一推荐的方式?

环境

  • Elasticsearch版本:

    7.17.9 * Elasticsearch Java Client版本:

    7.17.9 * Java版本:17

解决方案

是的,在Elasticsearch 7.17.9 版本中这是预期的行为,因为Terms聚合会将键转换为字符串,并且它支持字段的多种数据类型,如字符串、数值、布尔值等。你需要迁移到Elasticsearch 8.1.0 或更高版本,才能把键作为整数读取。

如果你确定 departmentId 始终会返回数值,你可以在Java代码中将其从字符串转换为整数。 下面的代码可在 8.1.0 下使用,无需再进行字符串到整数的转换。

Aggregate agg = response.aggregations().get("departmentIdAgg");

if (agg.isLterms()) {
    for (LongTermsBucket bucket : agg.lterms().buckets().array()) {
        int departmentId = Integer.parseInt(bucket.key());
        long docCount = bucket.docCount();

        // use departmentId and docCount
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章