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);完全匹配的模式!!!
学到了,有更深理解的交流下!!!!

猜你喜欢

转载自blog.csdn.net/qq_22155255/article/details/111735304