使用ElasticSearch统计嵌套字段中特定词汇的总出现次数
解决方案:利用Elasticsearch聚合高效统计嵌套字段特定词汇出现次数
你的场景里words是嵌套字段,直接遍历SearchHit累加的方式效率极低,完全可以通过嵌套聚合+过滤+计数的组合实现高效统计,无需返回任何文档数据。
核心逻辑
- 用
NestedAggregation进入words嵌套字段的上下文 - 在嵌套上下文内,通过过滤聚合筛选出
data字段匹配目标词汇的条目 - 最后用计数聚合直接统计筛选后的总数量
Java High Level Client 代码实现
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder; import org.elasticsearch.search.aggregations.metrics.ValueCountAggregationBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.io.IOException; public class NestedWordCounter { public static long getTargetWordTotalCount(RestHighLevelClient client, String targetWord) throws IOException { // 1. 初始化嵌套聚合,指定嵌套字段路径 NestedAggregationBuilder nestedAgg = AggregationBuilders.nested("nested_words_context", "words"); // 2. 过滤出data字段匹配目标词汇的嵌套条目 FilterAggregationBuilder filterAgg = AggregationBuilders.filter("filter_target_word", QueryBuilders.termQuery("words.data", targetWord)); // 3. 统计过滤后的条目总数 ValueCountAggregationBuilder countAgg = AggregationBuilders.count("total_match_count").field("words.data"); // 组装聚合层级:嵌套聚合 -> 过滤聚合 -> 计数聚合 filterAgg.subAggregation(countAgg); nestedAgg.subAggregation(filterAgg); // 构建搜索请求,仅返回聚合结果,不返回文档 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() .size(0) // 关键:不返回任何文档,大幅降低资源消耗 .aggregation(nestedAgg); SearchRequest searchRequest = new SearchRequest("documents") .source(sourceBuilder); // 执行请求并解析聚合结果 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); return response.getAggregations() .get("nested_words_context") .getAggregations() .get("filter_target_word") .getAggregations() .get("total_match_count") .getValue(); } }
关键注意事项
size(0)必须设置:这会让Elasticsearch只返回聚合统计结果,不传输任何文档数据,极大节省带宽和内存开销- 字段匹配方式:如果
data是text类型且开启了分词,termQuery匹配的是分词后的词项;若要精准匹配完整词汇,建议给data字段添加keyword子字段,然后用QueryBuilders.termQuery("words.data.keyword", targetWord)
内容的提问来源于stack exchange,提问作者user1485565
相关产品推荐
相关产品推荐

