SpringBoot集成Es实现分词检索

上一篇:
elasticsearch新建索引、mapping映射

一、项目中集成elasticsearch插件

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

二、配置服务器ip
在这里插入图片描述

三、发起搜索请求

/**
     * 分词查询
     * @param q
     * @return
     * @throws Exception
     */
    @RequestMapping("/search")
    public ModelAndView search(@RequestParam(value="q",required = false)String q, @RequestParam(value = "page",required = false)String page)throws Exception{
        ModelAndView mav=new ModelAndView();
        if(StringUtil.isEmpty(q)){
            mav.setViewName("index");
            mav.addObject("title","首页");
            return mav;
        }
        int pageSize=10;
        if(StringUtil.isEmpty(page)){
            page="1";
        }
        mav.addObject("q",q);
        List<ArticleInfo> articleInfoList = articleService.search(Integer.parseInt(page), pageSize, q);
        Long total = articleService.searchCount(q);
        mav.addObject("articleInfoList",articleInfoList);
        mav.addObject("total",total);
        mav.addObject("title",q);
        mav.addObject("modelName",q+" - 搜索结果");
        mav.addObject("pageCode", PageUtil.genSearchPagination("/search",total,Integer.parseInt(page),pageSize,q));
        mav.setViewName("result");
        return mav;
    }

四、分词检索:

/*
	返回的文档可能满足should子句的条件。
	在一个Bool查询中,如果没有must或者filter,
	有一个或者多个should子句,那么只要满足一个就可以返回
     */
    @Override
    public List<ArticleInfo> search(Integer page, Integer pageSize, String searchContent) {
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
        //BoolQueryBuilder:拼装连接(查询)条件
        // QueryBuilders:查询条件(关系)
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("name",searchContent))
                .should(QueryBuilders.matchQuery("content",searchContent));
        //NativeSearchQueryBuilder:将连接条件和聚合函数等组合
        NativeSearchQuery nativeSearchQuery=new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageRequest)
                .withIndices("test2")       //设置索引
                .withHighlightFields(new HighlightBuilder.Field("content"),new HighlightBuilder.Field("name"))
                .withHighlightBuilder(new HighlightBuilder().preTags("<font style='color:red'>").postTags("</font>")).build();

        //查询 并对获取到的数据进行处理、加工
        AggregatedPage<ArticleInfo> articleInfos = elasticsearchTemplate.queryForPage(nativeSearchQuery, ArticleInfo.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                ArrayList<ArticleInfo> articleInfos = new ArrayList<>();
                SearchHits hits = searchResponse.getHits(); //这便是获取到查询数据了
                for (SearchHit hit : hits) {
                    if (hits.getHits().length <= 0) {
                        return null; //没有数据 结束
                    }
                    Map<String, Object> sourceAsMap = hit.getSourceAsMap();//把结果作为一个map返回
                    // 根据map获取具体数据
                    String name = (String) sourceAsMap.get("name");
                    String content = (String) sourceAsMap.get("content");
                    String id = (String) sourceAsMap.get("id");
                    System.out.println("name:" + name);
                    System.out.println("content:" + content);

                    // 赋值给实体
                    ArticleInfo articleInfo = new ArticleInfo();
                    articleInfo.setId(Long.valueOf(id));
                    HighlightField contentHighlightField = hit.getHighlightFields().get("content");
                    if (contentHighlightField == null) {
                        articleInfo.setContent(content);//未查到高亮内容 设置非高亮的
                    } else {
                        //可能获取多个片段  这里只取第一个片段 因为bestFragment暂时不知道怎么获取
                        String highlightContent = hit.getHighlightFields().get("content").fragments()[0].toString();
                        // 去掉一些 换行符啊什么的
                        articleInfo.setContent(highlightContent.replaceAll("br", "").replaceAll("&nbsp;", "").replaceAll("_", ""));
                    }
                    HighlightField nameHighlightField = hit.getHighlightFields().get("name");
                    if (nameHighlightField == null) {
                        articleInfo.setName(name);
                    } else {
                        articleInfo.setName(hit.getHighlightFields().get("name").fragments()[0].toString());
                    }
                    articleInfos.add(articleInfo); //实体封装进集合里面
                }

                //作为一个集合 这里强转一下
                if (articleInfos.size() > 0) {
                    return new AggregatedPageImpl<T>((List<T>) articleInfos);
                }
                return null;
            }
        });
        return articleInfos==null?null:articleInfos.getContent();
    }

    @Override
    public Long searchCount(String searchContent) {
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("name",searchContent))
                .should(QueryBuilders.matchQuery("content",searchContent));

        NativeSearchQuery nativeSearchQuery=new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withIndices("test2").build();

        return elasticsearchTemplate.count(nativeSearchQuery);
    }

最终搜索结果如图:
在这里插入图片描述

发布了98 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_37767455/article/details/103038950