ElasticSearch解決中文搜索只能搜索單個字符的問題

問題描述

我寫了一個搜索的小項目,想利用es來實現高亮搜索,但是突然發現,我的搜索功能,只能搜出來英文譬如java,dior,vue等等,但是像醫學,高等數學就搜不出來了!

解決思路

一開始,我以爲是我的請求發送過去導致了中文亂碼

    new Vue({
        el:'#app',
        data:{
            keyword:'' ,//搜索的關鍵字
            results:[] //搜索的結果
        },
        methods:{
            searchKey(){
                var keyword = this.keyword;
                console.log(keyword);
                //對接後端接口
                axios.get('search/'+keyword+"/1/20").then(response=>{
                    console.log(response);
                    //綁定數據
                    this.results = response.data;
                })
            }
        }
    })

我以爲我的後臺收到的請求keyword搜索關鍵字亂碼了,但是後臺打印一下發現並沒有亂碼!!

再次尋找解決思路

我後來查閱資料好像說是分詞器的問題!!!誒,有道理
我就試了試單搜一個“醫”字或者“學”發現真能搜出來,那麼也就有一點眉目了,但是這個分詞器要改麼?我一開始覺得是詞庫沒有醫學之類的詞語,天真!!人家詞庫量太大,不可能沒有醫學兩個字的詞語,然後就問大佬,看博客,後來找到了一片類似的博客
老哥的原連接:https://blog.csdn.net/qq_44961149/article/details/107300665
有興趣的可以去看一下
原因出在:



  //實現搜索功能
    public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
   
   

        if (pageNo<1){
   
   
            pageNo = 1;
        }
        //條件搜索
        SearchRequest searchRequest = new SearchRequest("jd_goods");
        //構建搜索條件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //實現分頁功能
        searchSourceBuilder.from(pageNo);
        searchSourceBuilder.size(pageSize);
        //精確匹配
//        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title",keyword);
        MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("title", keyword);

        searchSourceBuilder.query(matchPhraseQueryBuilder);
        //60s加載時間
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        //這裏可以配置多個字段,信息等等
        //關閉多個高亮
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        //執行搜索
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //解析結果
        ArrayList<Map<String,Object>> list = new ArrayList<>();
        for (SearchHit documentFields : searchResponse.getHits().getHits()) {
   
   
            //解析我們的高亮字段
            Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            //原來的結果
            Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
            if (documentFields != null)
            {
   
   
                Text[] fragments = title.fragments();
                String n_title = "";
                //將高亮替換原來的字段
                for (Text text : fragments) {
   
   
                    n_title += text;
                }
                sourceAsMap.put("title",n_title);
            }
            list.add(sourceAsMap);
        }
        return list;
    }
    //精確匹配

// TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(“title”,keyword);
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery(“title”, keyword);
在這裏插入圖片描述
這一點當初看視頻學的時候有一些印象,說是term不會分詞。而keyword字段也不分詞,但是我呢加載了ik分詞器,ik分詞器是會默認分詞的,所以不能再使用TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(“title”,keyword);這種方法了,應該換成 MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery(“title”, keyword);完全匹配的模式!!!
學到了,有更深理解的交流下!!!!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章