📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 5.x – 8.x

1. 错误异常的基本描述 #

Aggregation [aggregation_name] cannot support regular expression style include/exclude settings as they can only be applied to string fields 是 Elasticsearch 在执行 terms 聚合(或其他支持 include/exclude 参数的聚合)时抛出的异常。该错误明确指出:正则表达式形式的 include/exclude 设置只对 字符串类型字段 有效,而当前聚合所引用的字段并非字符串类型。

常见现象 #

  • 发起包含 includeexclude 正则表达式的聚合请求后,Elasticsearch 直接返回 HTTP 400 Bad Request
  • 返回体中包含 AggregationExecutionExceptionillegal_argument_exception,并附带上述错误信息。
  • Kibana 的 Discover 或 Visualize 页面中配置的聚合无法正常渲染,出现红色错误提示。
  • 应用端日志中出现大量 ElasticsearchStatusExceptionSearchPhaseExecutionException,影响搜索与报表功能。

典型报错与异常栈 #

{
  "error": {
    "root_cause": [
      {
        "type": "aggregation_execution_exception",
        "reason": "Aggregation [my_agg] cannot support regular expression style include/exclude settings as they can only be applied to string fields. Use an array of values for include/exclude clauses"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "failed_shards": [
      {
        "reason": {
          "type": "aggregation_execution_exception",
          "reason": "Aggregation [my_agg] cannot support regular expression style include/exclude settings as they can only be applied to string fields. Use an array of values for include/exclude clauses"
        }
      }
    ]
  },
  "status": 400
}

对应的服务端日志片段:

[2026-01-28T10:00:00,000][DEBUG][o.e.s.a.TermsAggregator] Aggregation [my_agg] cannot support regular expression style include/exclude settings as they can only be applied to string fields
Caused by: AggregationExecutionException: Aggregation [my_agg] cannot support regular expression style ...
	at org.elasticsearch.search.aggregations.bucket.terms.TermsAggregatorFactory.buildAggregator(TermsAggregatorFactory.java:...)

2. 为什么会发生这个错误 #

Elasticsearch 的 terms 聚合 支持通过 includeexclude 参数对聚合桶进行过滤,过滤方式有两种:

方式说明适用字段类型
正则表达式(pattern用正则匹配 term 值仅限 keyword / string 类型
精确值数组(values用枚举值列表匹配所有类型(数值、keyword 等)

当使用正则表达式形式的 include/exclude 时,Elasticsearch 会在运行时检查字段的 DocValueFormat

  • 如果字段是 keyword 类型,format == DocValueFormat.RAW,正则匹配可以正常工作。
  • 如果字段是 longintegerdoubledateboolean 等非字符串类型,format != DocValueFormat.RAW,Elasticsearch 会主动抛出 AggregationExecutionException,拒绝执行正则过滤。

常见触发场景 #

  1. 对数值字段使用正则 include/exclude:如 {"include": "1.*"} 作用于 integerlong 类型字段。
  2. 对 date 类型字段使用正则过滤:如 {"include": "2024-.*"} 作用于 date 类型字段,日期在内部以数值形式存储。
  3. 字段类型变更后未同步更新查询:索引重建或 mapping 变更后,原本是 keyword 的字段变为 integer,而聚合 DSL 未相应调整。
  4. 多索引查询中字段类型不一致:跨索引搜索时,同一字段名在不同索引中的类型不同(一个为 keyword,另一个为 integer),导致部分分片报错。
  5. 动态 mapping 导致字段类型非预期:写入数据后字段被自动映射为 long,而聚合查询假设其为字符串。

3. 如何排查这个异常 #

建议按以下步骤定位根因:

第一步:确认报错的聚合名称和字段 #

从报错信息中提取聚合名称(如 my_agg),在 DSL 中找到对应聚合定义,确认其 field 值。

第二步:检查字段的 mapping 类型 #

# 查看指定索引中字段的 mapping
GET /your_index/_mapping/field/your_field

重点关注字段类型是否为 keywordtext(需用 .keyword 子字段),还是 long/integer/date 等非字符串类型。

第三步:确认 include/exclude 的写法 #

检查 DSL 中 includeexclude 的值是否为字符串形式的正则表达式(如 "1.*"),而非数组形式(如 ["1", "2", "3"])。

第四步:检查是否为跨索引不一致问题 #

# 查看所有相关索引中该字段的 mapping
GET /index1,index2,index3/_mapping/field/your_field

若不同索引中同一字段的类型不一致,则可能是跨索引搜索导致的问题。

排查注意事项 #

  • regex 与 array 的区分"include": "foo.*" 是正则,"include": ["foo", "bar"] 是数组,两者对字段类型的要求不同。
  • .keyword 子字段text 类型字段不能直接用于 terms 聚合的正则过滤,应使用 field.keyword
  • 动态 mapping 的影响:如果字段值全是数字,Elasticsearch 可能自动将其映射为 long,需检查索引模板或显式定义 mapping。

4. 如何解决这个错误 #

方案一:改用数组形式的 include/exclude(推荐) #

如果字段不是字符串类型,最简洁的修复方式是将正则表达式替换为精确值数组:

{
  "aggs": {
    "my_agg": {
      "terms": {
        "field": "status_code",
        "include": [200, 201, 202]
      }
    }
  }
}

方案二:将字段改为 keyword 类型后使用正则 #

如果业务上确实需要对字符串做正则匹配,应确保聚合字段为 keyword 类型:

{
  "aggs": {
    "my_agg": {
      "terms": {
        "field": "category.keyword",
        "include": "electronics|books"
      }
    }
  }
}

若原字段是 text 类型,使用其 .keyword 子字段;若原字段是数值类型且需要正则匹配,需在索引 mapping 中新增一个 keyword 类型的副本字段(copy_toruntime field)。

方案三:使用 runtime field 做类型转换 #

在查询时通过 runtime field 将非字符串字段转换为字符串形式:

{
  "runtime_mappings": {
    "status_code_str": {
      "type": "keyword",
      "script": {
        "source": "emit(doc['status_code'].value.toString())"
      }
    }
  },
  "aggs": {
    "my_agg": {
      "terms": {
        "field": "status_code_str",
        "include": "2.*"
      }
    }
  }
}

方案四:修正跨索引字段类型不一致问题 #

若多个索引中同一字段类型不一致,可:

  1. 使用 INFINI Gateway 在查询前统一字段映射。
  2. 重建索引,统一字段 mapping。
  3. 在查询中使用 runtime_mappings 为类型不一致的字段做兼容处理。

后续注意事项与推荐建议 #

  • 显式定义 mapping:避免使用动态 mapping,在索引模板中显式声明字段类型,尤其是聚合字段。
  • 区分 field 和 field.keywordtext 类型字段用于全文搜索,keyword 子字段用于聚合和精确匹配,正则过滤务必使用 keyword
  • 在 CI 中增加 DSL 校验:对聚合查询中的 include/exclude 使用方式做静态检查,提前发现字段类型不匹配问题。
  • 监控聚合失败率:通过 INFINI Console 监控集群中聚合异常的趋势,及时发现字段类型变更带来的影响。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 可查看集群中各索引的 mapping 一致性、聚合请求失败详情,以及字段类型分布,帮助快速判断是否为类型不匹配问题。
  • INFINI Gateway 可部署在 Elasticsearch 前端,对包含正则 include/exclude 的查询做合规检查与自动改写,防止非法查询到达后端集群。
  • 建议将聚合 DSL 的变更纳入网关的请求审计日志,结合 Console 的慢查询分析,建立从「查询异常 → 字段 mapping → 数据写入」的完整排查链路。

5. 小结 #

Aggregation cannot support regular expression style include/exclude 的本质原因是:正则表达式过滤只对字符串类型字段有效。解决该问题的核心思路是:先通过 _mapping API 确认字段类型,再根据实际情况选择「改用数组过滤」「切换到 keyword 字段」或「使用 runtime field 转换」三种方案之一。

在索引设计阶段显式定义 mapping、区分 textkeyword 的使用场景,可以从根本上避免此类问题。对于已上线的系统,借助 INFINI Console 和 INFINI Gateway 可以在不修改业务代码的前提下实现快速定位与防护。

相关错误 #

附:源码上下文 #

以下为触发该异常的 Elasticsearch 源码片段,便于深入理解异常触发条件:

if ((includeExclude != null) && (includeExclude.isRegexBased()) && valuesSourceConfig.format() != DocValueFormat.RAW) {
    throw new AggregationExecutionException("Aggregation [" + name + "] cannot support regular expression style "
        + "include/exclude settings as they can only be applied to string fields. Use an array of values for "
        + "include/exclude clauses");
}

从源码可以看出,当同时满足以下三个条件时,异常被抛出:

  1. includeExclude 不为空(即 DSL 中配置了 includeexclude);
  2. includeExclude.isRegexBased()true(即使用正则形式而非数组形式);
  3. valuesSourceConfig.format() != DocValueFormat.RAW(即字段不是字符串类型)。