Spring Boot 2.0 整合 ES 5 文章內容搜索實戰

本章內容
文章內容搜索思路
搜索內容分詞
搜索查詢語句
篩選條件
分頁、排序條件
小結html

1、文章內容搜索思路
上一篇講了在怎麼在 Spring Boot 2.0 上整合 ES 5 ,這一篇聊聊具體實戰。簡單講下如何實現文章、問答這些內容搜索的具體實現。實現思路很簡單:git

基於「短語匹配」並設置最小匹配權重值
哪來的短語,利用 IK 分詞器分詞
基於 Fiter 實現篩選
基於 Pageable 實現分頁排序
這裏直接調用搜索的話,容易搜出不盡人意的東西。由於內容搜索關注內容的鏈接性。因此這裏處理方法比較 low ,但願多交流一塊兒實現更好的搜索方法。就是經過分詞獲得不少短語,而後利用短語進行短語精準匹配。github

ES 安裝 IK 分詞器插件很簡單。第一步,在下載對應版本 https://github.com/medcl/elasticsearch-analysis-ik/releases。第二步,在 elasticsearch-5.5.3/plugins 目錄下,新建一個文件夾 ik,把 elasticsearch-analysis-ik-5.5.3.zip 解壓後的文件拷貝到 elasticsearch-5.1.1/plugins/ik 目錄下。最後重啓 ES 便可。spring

2、搜索內容分詞elasticsearch

安裝好 IK ,如何調用呢?優化

第一步,我這邊搜搜內容會以 逗號 拼接傳入。因此會先將逗號分割ui

第二步,在搜索詞中加入本身自己,由於有些詞通過 ik 分詞後就沒了... 這是個 bugthis

第三步,利用 AnalyzeRequestBuilder 對象獲取 IK 分詞後的返回值對象列表插件

第四步,優化分詞結果,好比都爲詞,則保留所有;有詞有字,則保留詞;只有字,則保留字code

核心實現代碼以下:

/**
     * 搜索內容分詞
     */
    protected List<String>      handlingSearchContent(String searchContent) {
 
             List<String> searchTermResultList = new ArrayList<>();
             // 按逗號分割,獲取搜索詞列表
             List<String> searchTermList = Arrays.asList(searchContent.split(SearchConstant.STRING_TOKEN_SPLIT));
 
             // 若是搜索詞大於 1 個字,則通過 IK 分詞器獲取分詞結果列表
             searchTermList.forEach(searchTerm -> {
                 // 搜索詞 TAG 自己加入搜索詞列表,並解決 will 這種問題
                 searchTermResultList.add(searchTerm);
                 // 獲取搜索詞 IK 分詞列表
                 searchTermResultList.addAll(getIkAnalyzeSearchTerms(searchTerm));
             });
 
             return searchTermResultList;
    }
 
    /**
     * 調用 ES 獲取 IK 分詞後結果
     */
    protected List<String>      getIkAnalyzeSearchTerms(String searchContent) {
             AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(),
                     AnalyzeAction.INSTANCE, SearchConstant.INDEX_NAME,      searchContent);
             ikRequest.setTokenizer(SearchConstant.TOKENIZER_IK_MAX);
             List<AnalyzeResponse.AnalyzeToken> ikTokenList =      ikRequest.execute().actionGet().getTokens();
 
             // 循環賦值
             List<String> searchTermList = new ArrayList<>();
             ikTokenList.forEach(ikToken -> {
                 searchTermList.add(ikToken.getTerm());
             });
 
             return handlingIkResultTerms(searchTermList);
    }
 
    /**
     * 若是分詞結果:洗髮水(洗髮、發水、洗、發、水)
     * - 均爲詞,保留
     * - 詞 + 字,只保留詞
     * - 均爲字,保留字
     */
    private List<String>      handlingIkResultTerms(List<String> searchTermList) {
             Boolean isPhrase = false;
             Boolean isWord = false;
             for (String term : searchTermList) {
                 if (term.length() > SearchConstant.SEARCH_TERM_LENGTH)      {
                     isPhrase = true;
                 } else {
                     isWord = true;
                 }
             }
 
             if (isWord & isPhrase) {
                 List<String> phraseList = new ArrayList<>();
                 searchTermList.forEach(term -> {
                     if (term.length() > SearchConstant.SEARCH_TERM_LENGTH)      {
                         phraseList.add(term);
                     }
                 });
                 return phraseList;
             }
 
             return searchTermList;
    }

3、搜索查詢語句

構造內容枚舉對象,羅列須要搜索的字段,ContentSearchTermEnum 代碼以下:

import lombok.AllArgsConstructor;
 
@AllArgsConstructor
public enum ContentSearchTermEnum {
 
    // 標題
    TITLE("title"),
    // 內容
    CONTENT("content");
 
    /**
     * 搜索字段
     */
    private String      name;
 
    public String      getName() {
             return name;
    }
 
    public void      setName(String name) {
             this.name = name;
    }
 
}

循環進行「短語搜索匹配」搜索字段,而後並設置最低權重值爲 1。核心代碼以下:

相關文章
相關標籤/搜索