Spring Data Elasticsearch是否支持Elasticsearch 6.2的Multi Search API?
使用Spring Data Elasticsearch结合ES6.2实现Multi Search API
我在使用Spring Data Elasticsearch配合ES6.2的时候也遇到过这个问题——确实当时的Spring Data Elasticsearch没有直接提供Multi Search的高层封装API,不过我们可以借助它底层的Elasticsearch客户端来实现,而且完全可以复用你已经用NativeSearchQueryBuilder写好的查询逻辑。
实现步骤
1. 构建多个NativeSearchQuery
首先你可以继续用NativeSearchQueryBuilder创建需要的搜索查询,比如:
// 第一个查询:匹配title包含"spring"的书籍 NativeSearchQuery bookTitleQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("title", "spring")) .withIndices("books") .withTypes("book") .build(); // 第二个查询:价格低于50的书籍 NativeSearchQuery bookPriceQuery = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.rangeQuery("price").lt(50)) .withIndices("books") .withTypes("book") .build();
2. 获取底层Elasticsearch客户端并构建MultiSearch请求
从ElasticsearchTemplate里拿到底层客户端(ES6.2支持RestHighLevelClient或TransportClient,这里分别给出两种示例):
如果你用的是RestHighLevelClient
// 从ElasticsearchTemplate获取底层客户端 RestHighLevelClient client = elasticsearchTemplate.getClient(); // 创建MultiSearch请求实例 MultiSearchRequest multiSearchRequest = new MultiSearchRequest(); // 把NativeSearchQuery转换成原生SearchRequest SearchRequest titleSearchRequest = new SearchRequest(bookTitleQuery.getIndices()); titleSearchRequest.types(bookTitleQuery.getTypes()); titleSearchRequest.source(bookTitleQuery.getSearchSourceBuilder()); SearchRequest priceSearchRequest = new SearchRequest(bookPriceQuery.getIndices()); priceSearchRequest.types(bookPriceQuery.getTypes()); priceSearchRequest.source(bookPriceQuery.getSearchSourceBuilder()); // 将两个搜索请求加入MultiSearch multiSearchRequest.add(titleSearchRequest); multiSearchRequest.add(priceSearchRequest);
如果你用的是TransportClient
// 从ElasticsearchTemplate获取底层客户端 TransportClient client = elasticsearchTemplate.getClient(); // 创建MultiSearch请求构建器 MultiSearchRequestBuilder multiSearchBuilder = client.prepareMultiSearch(); // 把NativeSearchQuery转换成原生SearchRequestBuilder SearchRequestBuilder titleSearchBuilder = client.prepareSearch(bookTitleQuery.getIndices()) .setTypes(bookTitleQuery.getTypes()) .setSource(bookTitleQuery.getSearchSourceBuilder()); SearchRequestBuilder priceSearchBuilder = client.prepareSearch(bookPriceQuery.getIndices()) .setTypes(bookPriceQuery.getTypes()) .setSource(bookPriceQuery.getSearchSourceBuilder()); // 将两个搜索请求加入MultiSearch multiSearchBuilder.add(titleSearchBuilder); multiSearchBuilder.add(priceSearchBuilder);
3. 执行MultiSearch请求并处理结果
提交请求后,遍历结果并处理,还可以利用ElasticsearchTemplate把返回的文档转换成你定义的实体类:
// RestHighLevelClient的执行方式 MultiSearchResponse response = client.msearch(multiSearchRequest, RequestOptions.DEFAULT); // (如果是TransportClient,执行方式是:MultiSearchResponse response = multiSearchBuilder.get();) // 遍历处理每个请求的结果 for (MultiSearchResponse.Item item : response.getResponses()) { if (!item.isFailure()) { // 获取单个搜索的响应 SearchResponse searchResponse = item.getResponse(); // 利用ElasticsearchTemplate将结果映射为实体类 List<Book> bookList = elasticsearchTemplate.mapResults(searchResponse, Book.class); // 这里可以根据业务需求处理bookList System.out.println("查询到书籍数量:" + bookList.size()); } else { // 处理请求失败的情况 String errorMsg = item.getFailureMessage(); System.err.println("搜索请求失败:" + errorMsg); } }
关键说明
- 之所以需要这么做,是因为Spring Data Elasticsearch在对应ES6.2的版本中,高层API(比如
ElasticsearchTemplate的query方法)没有封装Multi Search的能力,所以必须借助底层的Elasticsearch原生客户端来实现。 - 这种方式的好处是完全复用你已经用
NativeSearchQueryBuilder构建的查询逻辑,不需要重新写原生的查询DSL。
内容的提问来源于stack exchange,提问作者nalapoke
相关产品推荐
相关产品推荐

