前言

前面我们已经对spring 和 elasticsearch做了整合,这里便在前面的基础上使用es数据完成我们的项目列表及一系列查询分页排序及高亮等功能

 引入

 先看一下使用es数据完成列表及分页高亮等的效果图

 

 ElasticsearchTemplate 

  • ElasticsearchTemplate 封装ES客户端的一些原生api模板,方便实现一些查询
elasticsearchTemplate.queryForPage   #是查询一个分页列表,用的就是一个对象实例
    NativeSearchQuery                #是springdata中的查询条件
    NativeSearchQueryBuilder         #用于建造一个NativeSearchQuery查询对象
    QueryBuilders                    #设置查询条件,是ES中的类
    SortBuilders                     #设置排序条件
    HighlightBuilder                 #设置高亮显示

QueryBuilders 

  • QueryBuilders是ES中的查询条件构造器
QueryBuilders.boolQuery          #子方法must可多条件联查
QueryBuilders.termQuery          #精确查询指定字段
QueryBuilders.matchQuery         #按分词器进行模糊查询
QueryBuilders.rangeQuery         #按指定字段进行区间范围查询
#  大于等于      .from    .gte   
#  小于等于      .to      .lte    

NativeSearchQuery

  • 原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询,最终进行构建.build 可作为ElasticsearchTemplate. queryForPage的参数使用
//构建Search对象
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                //条件
                .withQuery(queryBuilder)
                //排序
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
                //高亮
                .withHighlightFields(name, ms)
                //分页
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                //构建
                .build();

        AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());

//queryForPage 参数一: NativeSearchQuery 封装的查询数据对象
               参数二: es对应索引实体类
               参数三: 调用高亮工具类

 总体查询数据至列表页面代码,每一步均有解释

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate; 

    @RequestMapping(value = "list")
    public String list(@ModelAttribute(value = "vo") QueryVo vo, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize, Model model){
        //高亮显示
        String pre = "<span style='color:red'>";
        String post = "</span>";
        //指定要高亮的字段将其加上头尾标签
        HighlightBuilder.Field name = new HighlightBuilder.Field("name").preTags(pre).postTags(post);
        HighlightBuilder.Field ms = new HighlightBuilder.Field("ms").preTags(pre).postTags(post);
        //查询高亮结果不分片,不加此条会按分词器高亮显示(数据变少)
        ms.numOfFragments(1);

        //多查询条件  must 可不断添加条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(StringUtils.isNoneBlank(vo.getName())){
                  //精确查询
                queryBuilder.must(QueryBuilders.termQuery("name.keyword",vo.getName()));
        }
        if(StringUtils.isNoneBlank(vo.getMs())){
                  //模糊查询
                queryBuilder.must(QueryBuilders.matchQuery("ms",vo.getMs()));
        }
        //根据指定字段区间查询   from(gte) 大于等于    to(lte)  小于等于
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
        if(vo.getStartpice() != null){
            rangeQuery.from(vo.getStartpice());
        }
        if(vo.getEndpice() != null){
            rangeQuery.to(vo.getEndpice());
        }
        queryBuilder.must(rangeQuery);

        //构建Search对象
        NativeSearchQuery build = new NativeSearchQueryBuilder()
                //条件
                .withQuery(queryBuilder)
                //排序
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
                //高亮
                .withHighlightFields(name, ms)
                //分页
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                //构建
                .build();

        AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());
        //封装分页数据至list集合中
        Page<Goods> page = new Page<>(pageNum, pageSize);
        //填充分页总条数
        page.setTotal(aggregatedPage.getTotalElements());
        //封装至pageinfo内,实现列表
        PageInfo<Goods> pg = new PageInfo<>(page);
        //将es查询到当前页的数据 封装至pg中
        pg.setList(aggregatedPage.getContent());
        
        //传入前端,实现列表页面
        model.addAttribute("pg",pg);
        return "list";
    }

认真看的伙伴可以看出上方我引入了高亮工具类,下面对高亮工具类进行详解(亮点) 

es高亮工具类(可直接复制,亲测有效)

public class Hig implements SearchResultMapper {
    /*
    searchResponse 封装高亮查询结果集
    clazz   要封装的es索引对应实体类对象
    pageable
     */
    @Override
    public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> clazz, Pageable pageable) {
        //获取es搜索数据集合对象
        SearchHits hits = searchResponse.getHits();
        //获取高亮搜索后数据的总条数
        long totalHits = hits.getTotalHits();
        //搭建存储数据集合对象
        ArrayList<T> list = new ArrayList<>();
        //判断高亮结果有数据
        if(hits.getHits().length > 0){
            //遍历数据集合
            for (SearchHit searchHit : hits) {
                //获取结果集中所有要高亮字段
                final Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                //把json串转为目标对象
                T t = JSON.parseObject(searchHit.getSourceAsString(), clazz);
                //获取目标对象的所有属性
                Field[] fields = clazz.getDeclaredFields();
                //遍历属性
                for (Field field : fields) {
                    //打破私有封装
                    field.setAccessible(true);
                    如果高亮的字段和要封装的对象的名字一致则值要重新封装
                    if(highlightFields.containsKey(field.getName())){
                        try {
                            //将查询到的数据进行高亮替换
                            field.set(t,highlightFields.get(field.getName()).fragments()[0].toString());
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
                //存入数据集合中
                list.add(t);
            }
        }
        //返回数据集合,排序对象,集高亮总条数
        return new AggregatedPageImpl<>(list,pageable,totalHits);
    }
}

解释下高亮是什么? 就是你百度时根据你搜索到的关键字高亮显示的特殊字体,例:下图


Thanks!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐