Найти уникальные значения полей в ElasticSearch, используя Spring Data ElasticsearchRepository - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть интерфейс, расширяющий ElasticsearchRepository, и я успешно создал методы для поиска, такие как:

Page<AuditResult> findByCustomerCodeAndHost(String customerCode, String host, Pageable pageable);

Теперь я хочу, чтобы была достигнута конечная точка, которая вернула бы мне все возможные значения хоста для этого customerCode, чтобы я мог создать раскрывающийся список в своем интерфейсе, чтобы выбрать значение для отправки в конечную точку findByCustomerCodeAndHost, например:

List<String> findUniqueHostByCustomerCode(String customerCode)

Возможно ли это используя ElasticsearchRepository?

Я знаю, что есть ключевое слово Distinct, которое я могу использовать как List<String> findDistinctByCustomerCode(String customerCode);, но это не позволяет мне указать поле хоста.


Редактировать: Вот как Я выполнил то, что хотел, но так как в настоящее время невозможно сделать это с ElasticsearchRepository, это не фактический «ответ».

Я создал класс Spring @RestController, который выставил @GetMapping Конечная точка REST, которая выполнила запрос агрегации.

Запрос в консоли kibana:

GET auditresult/_search
{
  "size": "0",
  "aggs" : {
    "uniq_custCode" : {
      "terms" : { "field" : "customerCode", "include": "<CUSTOMER_CODE>" },
        "aggs" : {
          "uniq_host" : {
           "terms" : { "field" : "host"}
          }
        }
      }
    }
  }

И, основываясь на этом вопросе Elast Агрегация icSearch с Java Я придумал

@GetMapping("/hosts/{customerCode}")
String getHostsByCustomer(@PathVariable String customerCode) {
    SearchRequest searchRequest = new SearchRequest("auditresult");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().size(0);
    IncludeExclude ie = new IncludeExclude(customerCode, "");
    TermsAggregationBuilder aggregation =
            AggregationBuilders
                    .terms("uniq_custCode").includeExclude(ie)
                    .field("customerCode")
                    .subAggregation(
                            AggregationBuilders
                                    .terms("uniq_host")
                                    .field("host")
                    );
    searchSourceBuilder.aggregation(aggregation);
    searchRequest.source(searchSourceBuilder);
    try {
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Terms cust = searchResponse.getAggregations().get("uniq_custCode");
        StringBuilder sb = new StringBuilder();
        sb.append("{\"hosts\":[");
        for (Terms.Bucket bucket : cust.getBuckets()) {
            Terms hosts = bucket.getAggregations().get("uniq_hosts");
            for (Terms.Bucket host : hosts.getBuckets()) {
                System.out.println(host.getKey());
                sb.append("\"" + host.getKey() + "\",");
            }
        }
        String out = sb.toString();
        out = out.substring(0, out.length() - 1);
        return out + "]}";
    } catch (IOException e) {
        e.printStackTrace();
        return "{\"hosts\":[]}";
    }
}

1 Ответ

1 голос
/ 25 апреля 2020

Здесь вам нужно что-то, что Spring Data вызывает как проекцию, для Spring Data MongoDB вы можете прочитать документацию , чтобы увидеть, как она там работает.

Увы, это не реализовано в Spring Data Elasticsearch (пока), я создал проблему в Jira для этого.

...