java 如何使用Spring Data Elasticsearch(最新版本)和Sping Boot 返回一个简单的聚合查询?

uqzxnwby  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(155)

我尝试使用Spring-Boot 3 + Spring Data ElasticSearch 5和Elasticsearch 8检索聚合品牌列表。
目前,我得到的结果,但从来没有汇总的。
我已经查阅了文档并在谷歌上搜索,但我找到的答案,我试图实现它们没有任何结论性的结果。
以下是我的三种方法:
使用Postman并返回聚合结果的基本查询:

{
    "size": 0,
    "aggs": {
        "distinct_brand": {
            "terms": {
                "field": "brand",
                "size": 10000,
                "order": {
                "_key": "asc"
        }
      }
    }
  }
}

测试1,使用StringQuery:

Query query = new StringQuery("{" +
            "        \"match_all\" : {}" +
            "    }," +
            "    \"size\": 100," +
            "    \"aggs\": {" +
            "        \"distinct_brand\": {" +
            "            \"terms\": {" +
            "                \"field\": \"brand\"," +
            "                \"size\": 10000," +
            "                \"order\": {" +
            "                \"_key\": \"asc\"" +
            "        }" +
            "      }" +
            "    }" +
            "  }");

    SearchHits<Brand> searchHits = elasticsearchOperations.search(query, Brand.class);

    List<Brand> brandList = searchHits.getSearchHits().stream()
            .map(SearchHit::getContent)
            .collect(Collectors.toList());

测试2,使用AggregationBuilders和withAggregation:

Aggregation aggregation = AggregationBuilders.terms(ta -> ta.field("brand").size(10000));

Query query = NativeQuery.builder()
        .withQuery(q -> q.matchAll(ma -> ma))
        .withAggregation("distinct_brand", aggregation)
        .withPageable(PageRequest.of(0, 10000))
        .build();

SearchHits<Brand> searchHits = elasticsearchOperations.search(query, Brand.class);

List<Brand> brandList = searchHits.getSearchHits().stream()
        .map(SearchHit::getContent)
        .collect(Collectors.toList());

测试3,使用JsonParser和SearchRequest:

JsonpMapper jsonpMapper = new JacksonJsonpMapper();
JsonParser jsonParser = Json.createParser(new StringReader("{" +
        "        \"match_all\" : {}" +
        "    }," +
        "    \"size\": 100," +
        "    \"aggs\": {" +
        "        \"distinct_brand\": {" +
        "            \"terms\": {" +
        "                \"field\": \"brand\"," +
        "                \"size\": 10000," +
        "                \"order\": {" +
        "                \"_key\": \"asc\"" +
        "        }" +
        "      }" +
        "    }" +
        "  }"));

SearchRequest request = SearchRequest._DESERIALIZER.deserialize(jsonParser, jsonpMapper);

NativeQueryBuilder nativeQueryBuilder = NativeQuery.builder();

for (Map.Entry<String, Aggregation> aggregationEntry : request.aggregations().entrySet()) {
    nativeQueryBuilder.withAggregation(aggregationEntry.getKey(), aggregationEntry.getValue());
}

Query query = nativeQueryBuilder.withPageable(PageRequest.of(0, 10000)).build();
    SearchHits<Brand> searchHits = elasticsearchOperations.search(query, Brand.class);
    
List<Brand> brandList = searchHits.getSearchHits().stream()
        .map(SearchHit::getContent)
        .collect(Collectors.toList());

你知道为什么吗?

kkbh8khc

kkbh8khc1#

测试1:只能在StringQuery中设置查询字符串,不能在聚合中设置,需要使用NativeQuery
测试2:这是发送查询的正确方法,您应该在查询中将maxResults设置为0,就像您在直接API调用中所做的那样。您看不到聚合的原因是因为它是作为返回的SearchHits对象的属性返回的,而您的代码收集matchall查询返回的对象。

cx6n0qe3

cx6n0qe32#

我是这样得到聚合的:

Aggregation aggregation = AggregationBuilders.terms(ta -> ta.field("brand").size(10000));

        Query query = NativeQuery.builder()
                .withMaxResults(0)
                .withQuery(q -> q.matchAll(ma -> ma))
                .withAggregation("distinct_brand", aggregation)
                .build();

        SearchHits<Vehicle> searchHits = searchOperations.search(query, Vehicle.class);

        ElasticsearchAggregations aggregations = (ElasticsearchAggregations) searchHits.getAggregations();
        List<ElasticsearchAggregation> aggregationsList = aggregations.aggregations();

        Buckets<StringTermsBucket> buckets = aggregationsList.get(0).aggregation().getAggregate().sterms().buckets();

        List<String> brandList = buckets.array().stream().map(bucket -> bucket.key().stringValue()).collect(Collectors.toList());

相关问题