#elasticsearch #spring-data #spring-data-elasticsearch #elasticsearch-aggregation
#эластичный поиск #весна-данные #spring-data-elasticsearch #elasticsearch-агрегация
Вопрос:
У меня есть следующий запрос JSON, который работает и делает то, что я хочу:
{
"aggs": {
"values": {
"filter": { "term": { "gender": "Male" } },
"aggs" : {
"names" : {
"terms" : { "field" : "name", "size":10000 }
}
}
}
},
"size":0
}
Он извлекает все присутствующие разные имена, где поле «generer» равно «Male». Это пример агрегации фильтров в elasticseach.
Сейчас я пытаюсь написать его с помощью spring-data-elasticsearch, и я попробовал это:
AbstractAggregationBuilder<TermsAggregationBuilder> agBuilder = AggregationBuilders.terms("name").field("name").size(10000);
Query query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.withFilter(QueryBuilders.termQuery("gender", "Male"))
.withPageable(EmptyPage.INSTANCE)
.addAggregation(agBuilder).build();
//Execute request over the cluster
SearchHits<Person> hits = elasticClient.search(query, Person.class);
//Retrieve the aggregation details
Aggregations aggs = hits.getAggregations();
ParsedStringTerms topTags = (ParsedStringTerms) aggs.get("name");
Обратите внимание, что EmptyPage.INSTANCE
это то же самое, что и PageRequest.of(0,0), является пользовательской реализацией для достижения этой цели.
К сожалению, он не делает то, что я хочу, поскольку игнорирует filter
предложение, возвращает имена мужчин и женщин. Я подозреваю, что, возможно withQuery
, он должен содержать другой Query
, но я не знаю, как передать другой NativeSearchQuery
этому методу.
Версии, которые я использую:
- Spring Data Elasticsearch: 4.0.3.ВЫПУСК
- Клиент Elasticsearch: 7.6.2
Как я мог бы написать приведенный выше запрос json с помощью spring-data-elasticsearch? Заранее спасибо.
Ответ №1:
Фильтр на самом деле должен быть внутри withQuery()
.
Query query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.termQuery("gender", "Male"))
...
withFilter
служит другой цели, а именно является post_filter
.
Также обратите внимание, что создаваемый вами запрос немного отличается от запроса, указанного в верхней части вашего вопроса, он похож на приведенный ниже и на самом деле является более оптимизированной версией, потому что вы фильтруете документы перед выполнением агрегации, вместо того, чтобы выполнять агрегацию по всем документам и рассматривать только тесопоставление фильтра. Конечный результат тот же, но производительность другая.
{
"size": 0,
"query": {
"term": {
"gender": "Male"
}
},
"aggs": {
"names": {
"terms": {
"field": "name",
"size": 10000
}
}
}
}
Комментарии:
1. Правильно! Это работает. Спасибо за совет, теперь я понимаю разницу между каждым запросом.