Агрегации фильтров Spring data elasticsearch

#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. Правильно! Это работает. Спасибо за совет, теперь я понимаю разницу между каждым запросом.