ElasticsearchTemplate实现高亮搜索

ElasticsearchTemplate实现高亮搜索

1 前言

搜索关键字高亮显示已经变成搜索不可缺少的一个部分,那当然我的搜索肯定也要有这样的功能塞,这样才能够显示我的高端不是吗(ಥ_ಥ)

2 Elasticsearch高亮基础

想要使用elasticsearchTemplate实现高亮搜索,肯定需要了解一下原本elasticsearch怎么高亮搜索,结果又是怎样的。

搜索语句结构

GET /blog/image/_search
{
  "query": {
    "match": {
      "tag": "武器"
    }
  },
  "highlight": {
    "fields": {
      "tag": {}
    }
  }
}

结果

3 高亮搜索

3.1 简易版本
 public List<Image> searchImageByEs(String search) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

     	//在tag,description域中搜索匹配的内容
     	//HighlightFields表示高亮设置
     	//new HighlightBuilder.Field("tag").preTags("<span style=\"color:red\">").postTags("</span>")表示设置高亮域为tag,并加上前置与后置标签
        NativeSearchQuery query = 
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery(search,"tag","description"))
                .withHighlightFields(new HighlightBuilder.Field("tag").preTags("<span style=\"color:red\">").postTags("</span>")).build();

     	//通过elasticsearchTemplate并重写SearchResultMapper方法来实现高亮搜索
        AggregatedPage<Image> images = elasticsearchTemplate.queryForPage(query, Image.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<Image> imageTemp = new ArrayList<>();
                
                //得到匹配的所有选项
                SearchHits hits = searchResponse.getHits();

                for (SearchHit hit : hits) {
                    if (hits.getHits().length <= 0) {
                        return null;
                    }

                    Image image = new Image();
                    image.setId(Integer.parseInt(hit.getId()));
                    image.setUrl(String.valueOf(hit.getSource().get("url")));
                    image.setDescription(String.valueOf(hit.getSource().get("description")));
                    image.setType(Integer.parseInt(String.valueOf(hit.getSource().get("type"))));
                    image.setTag(String.valueOf(hit.getSource().get("tag")));
					
                    //扩展性不强,使用反射更好
                    //防止标签不存在,描述存在的问题
                    if (hit.getHighlightFields().size()!=0) {
                        String highlightString = hit.getHighlightFields().get("tag").fragments()[0].toString();
                        image.setTag(highlightString);
                    }
                    imageTemp.add(image);
                }
                return new AggregatedPageImpl<>((List<T>)imageTemp);
            }
        });


        List<Image> imagesContent = images.getContent();
        return imagesContent;
    }

注意:这里的搜索域不要写错了,是一个常量(你已经创建了的域),不然getHighlightFields一直没有数据

3.2 增强版
public List<Image> highLightQueryPlus(String search) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        NativeSearchQuery query = queryBuilder.withQuery(QueryBuilders.multiMatchQuery(search,"tag","description"))
                .withHighlightFields(new HighlightBuilder.Field("tag").preTags("<span style=\"color:red\">").postTags("</span>"),new HighlightBuilder.Field("description").preTags("<span style=\"color:red\">").postTags("</span>")).build();

        AggregatedPage<Image> images = elasticsearchTemplate.queryForPage(query, Image.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<Image> imageTemp = new ArrayList<>();
                SearchHits hits = searchResponse.getHits();

                for (SearchHit hit : hits) {
                    if (hits.getHits().length <= 0) {
                        return null;
                    }

                    Image image = new Image();
                    image.setId(Integer.parseInt(hit.getId()));
                    image.setUrl(String.valueOf(hit.getSource().get("url")));
                    image.setDescription(String.valueOf(hit.getSource().get("description")));
                    image.setType(Integer.parseInt(String.valueOf(hit.getSource().get("type"))));
                    image.setTag(String.valueOf(hit.getSource().get("tag")));
                    setHighLight(hit,"tag",image);
                    setHighLight(hit,"description",image);
                    imageTemp.add(image);
                }
                return new AggregatedPageImpl<>((List<T>)imageTemp);
            }
        });


        List<Image> imagesContent = images.getContent();
        return imagesContent;
    }

反射调用属性的set方法设置高亮的内容

public void setHighLight(SearchHit searchHit, String field, Object object) {
        Map<String, HighlightField> highlightFieldMap = searchHit.getHighlightFields();
        HighlightField highlightField = highlightFieldMap.get(field);
        if (highlightField != null) {
            String highLightMessage = highlightField.fragments()[0].toString();
            String capitalize = StringUtils.capitalize(field);
            String methodName = "set"+capitalize;
            Class<?> clazz = object.getClass();
            try {
                Method setMethod = clazz.getMethod(methodName, String.class);
                setMethod.invoke(object, highLightMessage);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值