如何基于SpringBoot的Elasticsearch RestHighLevelClient扩展搜索功能
实现书籍搜索功能的具体方案
嘿,你已经把基础的增查(按ID)功能跑通了,接下来实现搜索功能其实很简单,我结合ES 6.1的RestHighLevelClient特性给你一步步拆解:
第一步:新增搜索接口(Controller层)
先在你的书籍Controller里加一个支持关键词、分页参数的搜索接口:
@RestController @RequestMapping("/books") public class BookController { @Autowired private BookService bookService; // 你的插入、按ID查询接口... @GetMapping("/search") public ResponseEntity<Map<String, Object>> searchBooks( @RequestParam String keyword, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) throws IOException { Map<String, Object> result = bookService.searchBooks(keyword, page, size); return ResponseEntity.ok(result); } }
第二步:实现搜索核心逻辑(Service层)
这部分是实现搜索的核心,我们用RestHighLevelClient构建多字段模糊搜索请求,还可以加上分页、高亮效果(可选):
@Service public class BookService { @Autowired private RestHighLevelClient restHighLevelClient; // 替换成你实际的ES索引名称 private static final String INDEX_NAME = "books"; public Map<String, Object> searchBooks(String keyword, int page, int size) throws IOException { // 1. 初始化搜索请求和源构建器 SearchRequest searchRequest = new SearchRequest(INDEX_NAME); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 2. 构建多字段匹配查询(同时搜索书名、作者、简介) // 开启*模糊匹配*,容错少量拼写错误 MultiMatchQueryBuilder matchQuery = QueryBuilders.multiMatchQuery(keyword, "title", "author", "description") .fuzziness(Fuzziness.AUTO); sourceBuilder.query(matchQuery); // 3. 设置分页(注意:ES的page是从0开始计数的) sourceBuilder.from(page); sourceBuilder.size(size); // 可选:添加高亮效果,让搜索关键词在结果中突出显示 HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("title") .preTags("<em>") .postTags("</em>"); sourceBuilder.highlighter(highlightBuilder); searchRequest.source(sourceBuilder); // 4. 执行搜索请求 SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 5. 处理搜索结果,转换成业务需要的格式 Map<String, Object> result = new HashMap<>(); result.put("total", searchResponse.getHits().getTotalHits()); List<Book> books = new ArrayList<>(); for (SearchHit hit : searchResponse.getHits().getHits()) { // 把ES返回的JSON文档转换成Book实体 Book book = new ObjectMapper().readValue(hit.getSourceAsString(), Book.class); // 替换高亮字段(如果存在) Map<String, HighlightField> highlightFields = hit.getHighlightFields(); if (highlightFields.containsKey("title")) { book.setTitle(highlightFields.get("title").getFragments()[0].toString()); } books.add(book); } result.put("books", books); return result; } // 你的插入、按ID查询方法... }
补充:Book实体类示例
确保你的实体类字段和ES文档的字段对应(可以用@JsonProperty指定映射关系):
public class Book { private String id; private String title; private String author; private String description; // 省略getter、setter、构造方法 }
第三步:测试搜索接口
用Postman或者浏览器直接调用即可,比如:GET 127.0.0.1:8080/books/search?keyword=Spring&page=0&size=5
你会得到包含总匹配条数、书籍列表的JSON响应,开启高亮后,书名里的关键词会被<em>标签包裹。
额外实用提示
- 如果需要精确匹配(比如按书籍分类搜索),可以用
TermQueryBuilder代替多匹配查询 - 确保RestHighLevelClient的依赖版本和ES服务器版本完全一致(ES 6.1对应client的6.1.x版本),避免兼容性问题
- 复杂组合查询(比如关键词+价格范围)可以用
BoolQueryBuilder把多个查询条件组合起来
内容的提问来源于stack exchange,提问作者AchillesVan
相关产品推荐
相关产品推荐

