Весенние данные ElastiSearch с фильтрами

Я пытаюсь выполнить агрегирование значений, отфильтрованных по некоторым условиям. Я использую ElasticSearchTemplate.query() метод данных Spring тоже выполнить запрос и получить результаты в экстракторе результатов. Я получаю хиты правильно (т.е. применяются фильтры и документы, соответствующие этим значениям, только извлекаются). Тем не менее, агрегация выполняется на всех документах. Я считаю, что агрегации должны применяться только к отфильтрованным значениям. Ниже приведен код, который я использую:

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();

К моему удивлению, этот запрос был выполнен правильно, и фильтры были применены и к агрегатам. Чтобы проанализировать дальше, я просмотрел код упругого поиска и обнаружил, что он использует 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! (т.е. фильтры были применены к запросу, но не к агрегатам. Является ли это ошибкой весенних данных? Если нет, то есть ли какой-то другой метод, который мне следует использовать для получения данных так, как я хочу?

Заранее спасибо.

1 ответ

Решение

Такое поведение разработано в Elasticsearch.

Проще говоря, вход в агрегаты И пост-фильтр - это набор документов, которые соответствуют query раздел тела запроса. Следовательно, агрегации не применяются к отфильтрованным документам.

Однако, если вы хотите, чтобы агрегаты применялись к отфильтрованным документам, "переместите фильтры внутрь query раздел ", то есть использовать фильтрованный запрос. Теперь вывод query В разделе будет отфильтрованный набор документов, и агрегации будут применяться к ним, как и ожидалось.

Поэтому для ваших требований используйте фильтрованный запрос вместо пост-фильтра.

Другие вопросы по тегам