ElasticSearch 是目前最風靡的開源框架之一,常用於站內搜索和日志分析。上一篇文章介紹了 ES 和 MySQL 數據同步,本文就介紹 ES 如何集成到 SpringBoot 中,實現基本的查詢。 本文主要用於站內搜索,可實現智能分詞,高亮關鍵字等功能,查詢速度也很快。 本文采用 ElasticSearch 6.5.0,客戶端是 Rest Client
一、整合 SpringBoot
1.pom.xml
<!-- ElasticSearch --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>6.5.0</version> </dependency> <!-- Java High Level REST Client --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>6.5.0</version> <exclusions> <exclusion> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> </exclusion> </exclusions> </dependency>
2.配置類 ESConfig.java
package com.liuyanzhao.sens.config; import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * ElasticSearch 配置類 * 實例化 client * * @author 言曌 * @date 2019/2/2 下午3:55 */ @Configuration public class ESConfig { @Bean public RestHighLevelClient client() { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"))); return client; } }
主要用於創建 client,然后要用的地方只需要注入,而不是在方法里,每次 new 一個。 3. Controller 層
@Autowired private RestHighLevelClient client; /** * 搜索 * * @param model model * @param page 當前頁碼 * @return 模板路徑/themes/{theme}/index */ @GetMapping(value = "/search/page/{page}") public String searchPage(Model model, @PathVariable(value = "page") Integer page, @RequestParam("keyword") String keyword) { //默認顯示20條 Integer size = 20; //所有日志數據,分頁 Page posts = new Page(page, size); // Page<Post> posts = postService.searchByKeywords(HtmlUtil.escape(keyword), pageable); page = page > 0 ? page : 0; //search request SearchRequest searchRequest = new SearchRequest("blog"); //search builder SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.matchQuery("postTitle", keyword)); sourceBuilder.from((page - 1) * size); sourceBuilder.size(size); sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //sort sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); //highlight HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("postTitle"); highlightTitle.preTags("<span class=\"highlight\">"); highlightTitle.postTags("</span>"); highlightBuilder.field(highlightTitle); sourceBuilder.highlighter(highlightBuilder); // add builder into request searchRequest.indices("blog"); searchRequest.source(sourceBuilder); //response SearchResponse searchResponse = null; try { searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } TimeValue took = searchResponse.getTook(); //search hits SearchHits hits = searchResponse.getHits(); long totalHits = hits.getTotalHits(); SearchHit[] searchHits = hits.getHits(); List<EsPost> postList = new ArrayList<>(); posts.setTotal((int) totalHits); for (SearchHit hit : searchHits) { String str = hit.getSourceAsString(); EsPost esPost = JSONObject.parseObject(str, EsPost.class); Map<String, HighlightField> highlightFields = hit.getHighlightFields(); HighlightField highlight = highlightFields.get("postTitle"); if (highlight != null) { Text[] fragments = highlight.fragments(); String fragmentString = fragments[0].string(); esPost.setPostTitle(fragmentString); } postList.add(esPost); } posts.setRecords(postList); model.addAttribute("is_index", true); model.addAttribute("posts", posts); model.addAttribute("prefix", "/search"); model.addAttribute("suffix", "?keyword=" + keyword); model.addAttribute("time", took); return this.render("search"); }
