如何禁用ElasticSearch TermsAggregationBuilder查询自动生成默认字段
Elasticsearch 7.x Java客户端生成查询携带额外默认字段的处理方案
这些额外字段是Elasticsearch 7.x版本Java High Level REST Client的原生序列化默认行为,所有非手动设置的输出字段均对应ES服务端的默认参数值,不会改变查询语义,也不会产生额外性能开销,如果没有强JSON格式校验要求,可直接使用无需处理。
如果确实需要剔除这些非预期字段,可通过以下两种可编程方式实现:
方案1:自定义序列化逻辑过滤默认值
该方案不需要修改原有查询、聚合的构建代码,仅在最终序列化JSON的环节增加过滤规则,侵入性最低。
实现步骤:
- 按照原有业务逻辑正常构建
SearchSourceBuilder、各类QueryBuilder和AggregationBuilder对象 - 自定义XContent序列化生成器,在写入字段时判断字段值是否对应ES官方默认值,匹配则跳过写入
- 常见需要过滤的默认值规则可直接硬编码:
- match查询:
operator="OR"、prefix_length=0、max_expansions=50、fuzzy_transpositions=true、lenient=false、zero_terms_query="NONE"、auto_generate_synonyms_phrase_query=true、boost=1 - bool查询:
adjust_pure_negative=true、boost=1 - range查询:
boost=1 - terms聚合:
min_doc_count=1、shard_min_doc_count=0、show_term_doc_count_error=false、默认追加的_key:asc次级排序 - date_histogram聚合:
offset=0、keyed=false、默认_key:asc排序
- match查询:
参考实现代码:
// 原有业务逻辑正常构建查询对象 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.size(0); sourceBuilder.query(QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("uri.raw", "sample_uri")) .must(QueryBuilders.rangeQuery("@timestamp") .from(1655145000000L) .to(1655231400000L) .format("epoch_millis")) ); sourceBuilder.aggregation(AggregationBuilders.terms("uri") .field("uri.raw") .size(1) // 显式指定仅按_count排序,避免客户端自动追加_key排序 .order(BucketOrder.count(false)) .subAggregation(/* 嵌套聚合逻辑 */) ); // 自定义序列化过滤默认字段 try (XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint()) { builder.startObject(); // 传入自定义参数,配合自定义XContentGenerator过滤默认字段 sourceBuilder.toXContent(builder, new ToXContent.MapParams(Map.of("exclude_defaults", "true"))); builder.endObject(); String finalQuery = builder.getOutputStream().toString(StandardCharsets.UTF_8); } catch (IOException e) { throw new RuntimeException(e); }
如果客户端原生不识别exclude_defaults参数,可以自行实现FilterXContentGenerator包装类,重写字段写入方法,在写入前匹配默认值规则,命中则直接跳过写入即可。
方案2:构建Builder时显式指定配置,避免客户端补全默认值
如果不想修改序列化逻辑,可以在构建查询、聚合对象时,显式指定和旧版本一致的配置,从源头避免客户端生成额外字段:
- Terms聚合不要使用无参的order方法,显式调用
.order(BucketOrder.count(false))指定仅按文档数倒序排序,就不会自动追加_key:asc的次级排序 - Date histogram聚合不要传入毫秒数值设置间隔,显式调用
.dateHistogramInterval(DateHistogramInterval.MINUTE),就会生成和旧版本一致的"interval": "1m"格式,不会自动转为60000ms - 所有查询、聚合如果不需要自定义boost权重,不需要额外调用setBoost方法,序列化时可统一过滤
boost=1的默认字段
注意:不建议通过修改ES客户端核心类源码的方式剔除默认字段,高版本客户端输出全量参数的设计初衷是为了规避跨版本默认值变更导致的查询语义不一致,强行修改核心逻辑可能在后续客户端版本升级时出现兼容性问题。
内容的提问来源于stack exchange,提问作者Vishnu Chaturvedi
相关产品推荐
相关产品推荐

