如何在SpringBoot中实现Elasticsearch的Multi-Match搜索查询
将Elasticsearch多字段查询转换为SpringBoot Java实现
我已在Kibana中验证以下查询,可针对products索引搜索关键词"novel",匹配description、name、id、price字段:
GET products/_search { "query": { "multi_match" : { "query": "novel", "fields": [ "description", "name","id" ,"price"] } } }
现需将该查询转换为SpringBoot项目的Java代码,以下是项目中现有Controller和ElasticSearchQuery类代码,请指导正确实现该搜索功能:
现有Controller类代码
package com.pixelTrice.elastic.search; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.List; @RestController public class ElasticSearchController { @Autowired private ElasticSearchQuery elasticSearchQuery; @PostMapping("/createOrUpdateDocument") public ResponseEntity<Object> createOrUpdateDocument(@RequestBody Product product) throws IOException { String response = elasticSearchQuery.createOrUpdateDocument(product); return new ResponseEntity<>(response, HttpStatus.OK); } @GetMapping("/getDocument") public ResponseEntity<Object> getDocumentById(@RequestParam String productId) throws IOException { Product product = elasticSearchQuery.getDocumentById(productId); return new ResponseEntity<>(product, HttpStatus.OK); } @DeleteMapping("/deleteDocument") public ResponseEntity<Object> deleteDocumentById(@RequestParam String productId) throws IOException { String response = elasticSearchQuery.deleteDocumentById(productId); return new ResponseEntity<>(response, HttpStatus.OK); } @GetMapping("/searchDocument") public ResponseEntity<Object> searchAllDocument() throws IOException { List<Product> products = elasticSearchQuery.searchAllDocuments(); return new ResponseEntity<>(products, HttpStatus.OK); } @GetMapping("/searching") public ResponseEntity<Object> searching() throws IOException{ List<Product> products = elasticSearchQuery.searching(); return new ResponseEntity<>(products,HttpStatus.OK); } }
现有ElasticSearchQuery类代码
package com.pixelTrice.elastic.search; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.core.*; import co.elastic.clients.elasticsearch.core.search.Hit; import org.apache.lucene.queryparser.flexible.core.builders.QueryBuilder; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; @Repository public class ElasticSearchQuery { @Autowired private ElasticsearchClient elasticsearchClient; private final String indexName = "products"; public String createOrUpdateDocument(Product product) throws IOException { IndexResponse response = elasticsearchClient.index(i -> i .index(indexName) .id(product.getId()) .document(product) ); if (response.result().name().equals("Created")) { return new StringBuilder("Document has been successfully created.").toString(); } else if (response.result().name().equals("Updated")) { return new StringBuilder("Document has been successfully updated.").toString(); } return new StringBuilder("Error while performing the operation.").toString(); } public Product getDocumentById(String productId) throws IOException { Product product = null; GetResponse<Product> response = elasticsearchClient.get(g -> g .index(indexName) .id(productId), Product.class ); if (response.found()) { product = response.source(); System.out.println("Product name " + product.getName()); } else { System.out.println("Product not found"); } return product; } public String deleteDocumentById(String productId) throws IOException { DeleteRequest request = DeleteRequest.of(d -> d.index(indexName).id(productId)); DeleteResponse deleteResponse = elasticsearchClient.delete(request); if (Objects.nonNull(deleteResponse.result()) && !deleteResponse.result().name().equals("NotFound")) { return new StringBuilder("Product with id " + deleteResponse.id() + " has been deleted.").toString(); } System.out.println("Product not found"); return new StringBuilder("Product with id " + deleteResponse.id() + " does not exist.").toString(); } public List<Product> searchAllDocuments() throws IOException { SearchRequest searchRequest = SearchRequest.of(s -> s.index(indexName)); SearchResponse searchResponse = elasticsearchClient.search(searchRequest, Product.class); List<Hit> hits = searchResponse.hits().hits(); List<Product> products = new ArrayList<>(); for (Hit object : hits) { System.out.print(((Product) object.source())); products.add((Product) object.source()); } return products; } public List<Product> searching() throws IOException{ SearchRequest searchRequest = new SearchRequest(); searchRequest.indices(indexName); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); QueryBuilder cluase0 = QueryBuilders.multiMatchQuery(queryString, "name", "id", "description", "price"); MultiMatchQueryBuilder multiMatchQueryBuilder1 = new MultiMatchQueryBuilder(queryString, "firstName", "lastName", "password", "emailId", "userId", "mobileNumber"); multiMatchQueryBuilder1.operator(Operator.AND); searchSourceBuilder.query(multiMatchQueryBuilder1); } }
修正后的实现代码
1. 修改Controller接口,接收搜索关键词
将/searching接口改为接收查询参数,支持动态传入搜索关键词:
@GetMapping("/searching") public ResponseEntity<Object> searching(@RequestParam String keyword) throws IOException{ List<Product> products = elasticSearchQuery.searchByKeyword(keyword); return new ResponseEntity<>(products,HttpStatus.OK); }
2. 重构ElasticSearchQuery中的搜索方法
你当前混合使用了旧版Elasticsearch High Level Client API与新版co.elastic.clients客户端,需统一使用新版DSL构建查询,避免兼容性问题。替换原searching方法为以下实现:
public List<Product> searchByKeyword(String keyword) throws IOException { // 构建与Kibana查询完全对应的multi_match查询 SearchResponse<Product> response = elasticsearchClient.search(s -> s .index(indexName) .query(q -> q .multiMatch(m -> m .query(keyword) .fields("description", "name", "id", "price") ) ), Product.class); List<Hit<Product>> hits = response.hits().hits(); List<Product> products = new ArrayList<>(); for (Hit<Product> hit : hits) { products.add(hit.source()); } return products; }
3. 清理冗余代码
删除ElasticSearchQuery中未使用的旧API导入(如SearchSourceBuilder、QueryBuilders等)及无效的原searching方法,减少代码冗余。
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

