Запрос на агрегацию данных Spring. - PullRequest
0 голосов
/ 28 июня 2019

Я пытаюсь сделать приведенный ниже запрос эластичного поиска для работы с данными пружины. Цель - вернуть уникальные результаты для поля "serviceName". Точно так же, как SELECT DISTINCT serviceName FROM table сравнивал бы с базой данных SQL.

{
  "aggregations": {
    "serviceNames": {
      "terms": {
        "field": "serviceName"
      }
    }
  },
  "size":0
}

Я настроил поле в качестве ключевого слова, и оно прекрасно работало в API index_name/_search согласно приведенному ниже фрагменту ответа:

"aggregations": {
        "serviceNames": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "service1",
                    "doc_count": 20
                },
                {
                    "key": "service2",
                    "doc_count": 8
                },
                {
                    "key": "service3",
                    "doc_count": 8
                }
            ]
        }
    }

Моя проблема в том, что тот же запрос не работает в данных Spring, когда я пытаюсь запустить с StringQuery Я получаю ошибку ниже. Я предполагаю, что он использует другой API для выполнения запросов.

Cannot execute jest action , response code : 400 , error : {"root_cause":[{"type":"parsing_exception","reason":"no [query] registered for [aggregations]","line":2,"col":19}],"type":"parsing_exception","reason":"no [query] registered for [aggregations]","line":2,"col":19} , message : null

Я пытался использовать тип SearchQuery для достижения тех же результатов, без дубликатов и загрузки объектов, но мне не повезло. Приведенный ниже sinnipet показывает, как я пытался это сделать.

final TermsAggregationBuilder aggregation = AggregationBuilders
                .terms("serviceName")
                .field("serviceName")
                .size(1);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices("index_name")
                  .withQuery(matchAllQuery())
                  .addAggregation(aggregation)
                  .withSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                  .withSourceFilter(new FetchSourceFilter(new String[] {"serviceName"}, new String[] {""}))
                  .withPageable(PageRequest.of(0, 10000))
                  .build();

Кто-нибудь знает, как добиться отсутствия загрузки объекта и четкого агрегирования свойств объекта в данных пружины?

Я много раз безуспешно пытался напечатать запросы к данным Spring, но не смог, может быть, потому что я использую реализацию com.github.vanroy.springdata.jest.JestElasticsearchTemplate. Я получил запрос частей со следующим:

logger.info("query:" + searchQuery.getQuery());
logger.info("agregations:" + searchQuery.getAggregations());
logger.info("filter:" + searchQuery.getFilter());
logger.info("search type:" + searchQuery.getSearchType());

Он печатает:

query:{"match_all":{"boost":1.0}}
agregations:[{"serviceName":{"terms":{"field":"serviceName","size":1,"min_doc_count":1,"shard_min_doc_count":0,"show_term_doc_count_error":false,"order":[{"_count":"desc"},{"_key":"asc"}]}}}]
filter:null
search type:DFS_QUERY_THEN_FETCH

1 Ответ

0 голосов
/ 28 июня 2019

Я понял, может быть, может помочь кому-то.Агрегация идет не с результатами запроса, а с самим собой и не отображается ни на один объект.Результаты Objects, по-видимому, являются примерами запроса ввода-вывода, который выполнил ваш агрегат (не уверен, может быть).Я закончил тем, что создал метод, который может симулировать то, что будет на SQL SELECT DISTINCT your_column FROM your_table, но я думаю, что это будет работать только для полей ключевых слов, они имеют ограничение в 256 символов, если я не ошибаюсь.Я объяснил некоторые строки в комментариях.Спасибо @Val, поскольку я смог понять это только при отладке в код Jest и проверить сгенерированный запрос и необработанный ответ.

public List<String> getDistinctField(String fieldName) {
    List<String> result = new ArrayList<>();

    try {
        final String distinctAggregationName = "distinct_field"; //name the aggregation

        final TermsAggregationBuilder aggregation = AggregationBuilders
                .terms(distinctAggregationName)
                .field(fieldName)
                .size(10000);//limits the number of aggregation list, mine can be huge, adjust yours

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices("your_index")//maybe can be omitted
                .addAggregation(aggregation)
                .withSourceFilter(new FetchSourceFilter(new String[] { fieldName }, new String[] { "" }))//filter it to retrieve only the field we ar interested, probably we can take this out.
                .withPageable(PageRequest.of(0, 1))//can't be zero, and I don't want to load 10 results every time it runs, will always return one object since I found no "size":0 in query builder
                .build();
//had to use the JestResultsExtractor because com.github.vanroy.springdata.jest.JestElasticsearchTemplate don't have an implementation for ResultsExtractor, if you use Spring defaults, you can probably use it.
    final JestResultsExtractor<SearchResult> extractor = new JestResultsExtractor<SearchResult>() {
                @Override
                public SearchResult extract(SearchResult searchResult) {
                    return searchResult;
                }
            };

            final SearchResult searchResult = ((JestElasticsearchTemplate) elasticsearchOperations).query(searchQuery,
                    extractor);
            final MetricAggregation aggregations = searchResult.getAggregations();
            final TermsAggregation termsAggregation = aggregations.getTermsAggregation(distinctAggregationName);//this is where your aggregation results are, in "buckets".
            result = termsAggregation.getBuckets().parallelStream().map(TermsAggregation.Entry::getKey)
                    .collect(Collectors.toList());

        } catch (Exception e) {
            // threat your error here.
            e.printStackTrace();
        }
        return result;

    }
...