我正在尝试对某些条件筛选的值执行聚合。我正在使用Spring数据的ElasticSearchTemplate.query()方法执行查询并在结果提取器中获取结果。 我正确地获得了命中(即应用过滤器并且仅检索匹配这些值的文档)。但是,会对所有文档执行聚合。我认为聚合应该只应用于过滤值。以下是我正在使用的代码:
SearchQuery query = //get the query
SearchResponse hits = template.query(query, new ResultsExtractor<SearchResponse>() {
@Override
public SearchResponse extract(SearchResponse response) {
return response;
}
});
为了进一步调试问题,我编写了代码来执行查询而不是使用spring数据。以下是代码:
SearchRequestBuilder builder = esSetup.client().prepareSearch("document");
builder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), query.getFilter()));
builder.addFields(query.getFields().toArray(new String[query.getFields().size()]));
for(AbstractAggregationBuilder aggregation : query.getAggregations()){
builder.addAggregation(aggregation);
}
SearchResponse response = builder.get();
令我惊讶的是,此查询正确执行,并且过滤器也应用于聚合。为了进一步分析,我浏览了elasticsearchtemplate的代码,发现它使用setPostFilter
方法来设置过滤器。然后我修改了我的代码以这种方式设置过滤器:
SearchRequestBuilder builder = esSetup.client().prepareSearch("document");
// builder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), query.getFilter()));
builder.setPostFilter(query.getFilter());
builder.addFields(query.getFields().toArray(new String[query.getFields().size()]));
for(AbstractAggregationBuilder aggregation : query.getAggregations()){
builder.addAggregation(aggregation);
}
SearchResponse response = builder.get();
当我执行上面的代码时,它表现出与spring数据相同的行为! (即过滤器适用于查询但不适用于聚合。 这是弹簧数据的错误吗?如果没有,那么,我是否应该使用其他方法来按照我想要的方式检索数据?
提前致谢。
答案 0 :(得分:8)
此行为是在Elasticsearch中设计的。
简单来说,对聚合和后置过滤器的输入是与请求正文的query
部分匹配的文档集。因此,聚合不会应用于过滤的文档。
但是,如果您确实要在已过滤的文档上应用聚合,请在query
部分&#34;内移动过滤器,即使用filtered query。现在query
部分的输出将是过滤的文档集,并且聚合将按预期应用于它们。
因此,根据您的要求,请使用过滤后的查询而不是后置过滤器。