您好,登錄后才能下訂單哦!
本篇內容介紹了“怎么在自己的項目中引入ElasticSearch搜索引擎”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
在大多數系統中,都需要支持搜索的功能,以簡單博客系統為例,雖然說Mysql也可以通過模糊查詢匹配到對應的數據,但是效率實在太低。這個時候就需要拿出分布式搜索引擎ElasticSearch了。本博客重點在于ES的集成使用,因此前端采用最簡單的方式呈現,大家只需要關注后端邏輯即可。(本博客基于ES7.6.1,和ES6.X版本有較大差異)
依賴主要就是web、es以及thymleaf相關:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <!--thymleaf相關--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency>
編寫ES的配置類,編寫連接信息,之后直接通過Autowired連接即可:
@Configuration public class ElasticSearchConfig { @Bean public RestHighLevelClient restHighLevelClient(){ RestHighLevelClient client=new RestHighLevelClient( RestClient.builder( new HttpHost("192.168.78.128",9200,"http") ) ); return client; } }
編寫一個類用來存儲要存儲的數據,我這里為了演示只在es中插入標題和作者的信息
@Data @AllArgsConstructor public class BlogDO { private String title; private String author; }
最后新建一個IndexController和IndexService以及IndexServiceImpl,接下來會使用。最終的目錄結構如下:
要做數據的搜索,首先第一步就是數據的導入。在真實的業務場景中,數據的導入有很多方式。一種是當新增數據時在代碼邏輯中做增量的導入操作,或者是由數倉團隊負責數據的增量導入。我接觸到的業務中,后端程序員不需要去關注導入的操作,這個步驟是數倉團隊做的。
在我們個人的博客系統中,可以在新增博客后立刻同步數據到ES,也可以先通過消息中間件發送一條消息,消費者定期去讀取消息新增數據。
這里演示就直接導入了:
@Controller public class IndexController { @Autowired private IndexService indexService; @ResponseBody @GetMapping("/prepareData") public String prepareData(){ String result=indexService.prepareData(); return result; } }
具體的service實現如下:
@Service public class IndexServiceImpl implements IndexService { @Autowired private RestHighLevelClient restHighLevelClient; @Override public String prepareData() { List<BlogDO> blogDOS = new ArrayList<>(); blogDOS.add(new BlogDO("ElasticSearch究竟是個什么東西", "Java魚仔")); blogDOS.add(new BlogDO("SpringBoot+SpringSecurity實現基于真實數據的授權認證", "Java魚仔")); blogDOS.add(new BlogDO("Dubbo兩小時快速上手教程(直接代碼、Spring、SpringBoot)", "Java魚仔")); blogDOS.add(new BlogDO("淺析五種最常用的Java加密算法", "Java魚仔")); blogDOS.add(new BlogDO("Java程序員需要知道的操作系統知識匯總", "Java魚仔")); blogDOS.add(new BlogDO("一步步教你如何在SpringBoot項目中引入支付功能", "Java魚仔")); blogDOS.add(new BlogDO("Zookeeper實現分布式鎖的原理是什么?", "Java魚仔")); blogDOS.add(new BlogDO("一個成熟的Java項目如何優雅地處理異常", "Java魚仔")); blogDOS.add(new BlogDO("基于SpringBoot實現文件的上傳下載", "Java魚仔")); blogDOS.add(new BlogDO("如何用Java寫一個規范的http接口?", "Java魚仔")); BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout("10s"); blogDOS.stream().forEach(x -> { bulkRequest.add(new IndexRequest("blog_index").source(JSON.toJSONString(x), XContentType.JSON)); }); BulkResponse responses=null; try { responses = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return String.valueOf(responses.status()); } }
我選取了自己的幾篇博客文章,多執行幾次接口,保證ES中有幾十條數據供測試使用即可。
接下來就是搜索的過程了,搜索的邏輯其實比較簡單,具體的代碼就按照上一篇博客中的方式來編寫,在真實業務場景中,每個公司可能會有自己的封裝搜索方法:
IndexController中增加一個方法:
@GetMapping("/search") public String search(@RequestParam("keywords")String keywords, @RequestParam("pageNum")String pageNum, @RequestParam("pageSize")String pageSize, Model model){ List<Map<String,Object>> list=indexService.searchByKeywords(keywords,pageNum,pageSize); model.addAttribute("datas",list); return "search"; }
具體實現類中增加方法:
@Override public List<Map<String, Object>> searchByKeywords(String keywords, String pageNum, String pageSize) { return this.searchData(keywords,Integer.parseInt(pageNum),Integer.parseInt(pageSize)); } public List<Map<String,Object>> searchData(String keywords, int pageNum, int pageSize){ if (pageNum<1){ pageNum=1; } //生成搜索對象 SearchRequest request = new SearchRequest("blog_index"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //設置分頁參數 searchSourceBuilder.from(pageNum); searchSourceBuilder.size(pageSize); //設置搜索的字段 MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keywords); searchSourceBuilder.query(matchQueryBuilder); searchSourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS)); request.source(searchSourceBuilder); SearchResponse search=null; try { search = restHighLevelClient.search(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } //將結果返回 List<Map<String,Object>> result=new ArrayList(); SearchHit[] hits = search.getHits().getHits(); for (SearchHit searchHit:hits){ result.add(searchHit.getSourceAsMap()); } return result; }
簡單寫一個前端頁面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"><!--引入thymeleaf--> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <div th:each="datas:${datas}"> <span th:text="${datas.author}"/> <span th:utext="${datas.title}"/> <hr/> </div> </div> </body> </html>
跑起來看一下,訪問
http://localhost:8080/search?keywords=Java&pageNum=1&pageSize=10
在鏈接中,我關鍵詞填了Java,pageNum是1,每頁展示10行,可以看到和Java相關的數據就被查出來了。
在百度搜索Java時,可以看到查詢出來的Java被高亮顯示了,之前在講ES語法的時候,我們也知道了ES支持高亮查詢,下面就通過代碼來實現。
稍微修改一下搜索的代碼,增加高亮配置,在返回值中用高亮字符串替換原來的字符串。
public List<Map<String,Object>> searchHighLightData(String keywords, int pageNum, int pageSize){ if (pageNum<1){ pageNum=1; } SearchRequest request = new SearchRequest("blog_index"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.from(pageNum); searchSourceBuilder.size(pageSize); //高亮構造器 HighlightBuilder highlightBuilder=new HighlightBuilder(); //高亮查詢字段 highlightBuilder.field("title"); //是否將所有匹配到的字段高亮顯示,false表示只顯示一個 highlightBuilder.requireFieldMatch(false); //高亮的標簽 highlightBuilder.preTags("<span style='color:red'>"); highlightBuilder.postTags("</span>"); searchSourceBuilder.highlighter(highlightBuilder); MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", keywords); searchSourceBuilder.query(matchQueryBuilder); searchSourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS)); request.source(searchSourceBuilder); SearchResponse search=null; try { search = restHighLevelClient.search(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } List<Map<String,Object>> result=new ArrayList(); SearchHit[] hits = search.getHits().getHits(); //遍歷結果,將高亮返回值title替換到原來的title中 for (SearchHit searchHit:hits){ Map<String, Object> sourceAsMap = searchHit.getSourceAsMap(); Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); HighlightField title = highlightFields.get("title"); if (title!=null){ StringBuilder highLightTitle=new StringBuilder(); Text[] texts = title.fragments(); for(Text text:texts){ highLightTitle.append(text); } sourceAsMap.put("title",highLightTitle); } result.add(sourceAsMap); } return result; }
繼續訪問
http://localhost:8080/search?keywords=Java&pageNum=1&pageSize=10,
通過斷點可以看到,搜索的關鍵詞已經被我們設置的span標簽包住了。
在前端thymeaf中,我是用了th:utext,這個標簽可以將Html解析,最終的高亮顯示如下:
“怎么在自己的項目中引入ElasticSearch搜索引擎”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。