Spring 带过滤器的数据 ElasticSearch 聚合
Spring data ElastiSearch aggregations with filters
我正在尝试对按某些条件过滤的值执行聚合。我正在使用 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 数据相同的行为! (即过滤器应用于查询但不是聚合。
这是spring data es的bug吗?如果没有,那么我是否应该使用任何其他方法以我想要的方式检索数据?
提前致谢。
此行为是 Elasticsearch 的设计使然。
简而言之,聚合和 post 过滤器的输入是与请求正文的 query
部分匹配的文档集。因此,聚合不会应用于过滤后的文档。
但是,如果您确实希望对过滤后的文档应用聚合,"move the filters inside the query
section",即使用 filtered query。现在 query
部分的输出将是过滤后的文档集,聚合将按预期应用于它们。
因此,根据您的要求,使用过滤查询而不是 post 过滤器。
我正在尝试对按某些条件过滤的值执行聚合。我正在使用 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 数据相同的行为! (即过滤器应用于查询但不是聚合。 这是spring data es的bug吗?如果没有,那么我是否应该使用任何其他方法以我想要的方式检索数据?
提前致谢。
此行为是 Elasticsearch 的设计使然。
简而言之,聚合和 post 过滤器的输入是与请求正文的 query
部分匹配的文档集。因此,聚合不会应用于过滤后的文档。
但是,如果您确实希望对过滤后的文档应用聚合,"move the filters inside the query
section",即使用 filtered query。现在 query
部分的输出将是过滤后的文档集,聚合将按预期应用于它们。
因此,根据您的要求,使用过滤查询而不是 post 过滤器。