ElasticSearch7.6版本以上实现搜索关键字高亮

一、环境搭建

1.启动ElasticSearch服务器(以7.7.0版为例)
下载地址:https://www.elastic.co/cn/downloads/elasticsearch
在这里插入图片描述
访问localhost:9200返回以上信息则表示服务启动成功。

2.启动Kibana
Kibana 下载地址:https://www.elastic.co/cn/downloads/kibana
访问: http://localhost:5601/app/kibana#/home?_g=(),kibana默认会自动连接本地的es服务器。
在这里插入图片描述
出现以上的控制台表示kibana启动成功。
在这里插入图片描述
点击Dev Tools选项进入开发工具,插入几条测试数据
在这里插入图片描述
3.创建一个SpringBoot项目,引入依赖

<dependencies>

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

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.7.0</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

注意:要特别指定ElasticSearch的版本和依赖的版本一致

  <properties>
        <java.version>1.8</java.version>
<elasticsearch.version>7.7.0</elasticsearch.version>
    </properties>

4.编写一个ElasticSearch配置类,给容器中添加一个可以访问的es的客户端。

@Configuration
public class ElasticSearchConfig {

    public static final RequestOptions COMMON_OPTIONS;
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        COMMON_OPTIONS = builder.build();
    }

    @Bean
    public RestHighLevelClient es(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("localhost", 9200, "http")));
        return client;
    }

}

二、实现高亮查询

实现高亮结果的总体思路是:
(1 构建一个检索请求 (SearchRequest)。
(2 构建一个搜索源(SearchSourceBuilder),可以为这个对象添加搜索条件,超时时间,高亮属性等。
(3 构建一个高亮器(HighlightBuilder),为其指定高亮的属性以及前缀和后缀等,例如想让 “”西红柿“”这三个字高亮显示,就可以为这个关键词加前缀<span style="color:red">,后缀</span>。这样整个结果就是<span style="color:red">西红柿</span>,将来再通过html网页解析就可以实现结果高亮。
(4 为SearchRequest设置SearchSourceBuilder,执行检索,返回SearchResponse。
(5 拿到SearchResponse中的hits的hits,遍历这个hits数组,拿到之前设置的高亮字段进行拼接,再讲拼接好的值替换旧的值。

实例代码如下:


@Service
public class ESProductService {

   @Autowired
   private RestHighLevelClient client;

   public List<ESProductTO> searchProduct(String keywords) throws IOException {
        List<ESProductTO> esProductTOS = new ArrayList<>();
        //1.构建检索条件
        SearchRequest searchRequest = new SearchRequest();
        //2.指定要检索的索引库
        searchRequest.indices("product");
        //3.指定检索条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        sourceBuilder.query(QueryBuilders.multiMatchQuery(keywords,"productName"));

        //4.结果高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(true); //如果该属性中有多个关键字 则都高亮
        highlightBuilder.field("productName");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");

        sourceBuilder.highlighter(highlightBuilder);
        searchRequest.source(sourceBuilder);
        SearchResponse response = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
        //如果不做高亮,则可以直接转为json,然后转为对象
//            String value = hit.getSourceAsString();
//            ESProductTO esProductTO = JSON.parseObject(value, ESProductTO.class);
            //解析高亮字段
            //获取当前命中的对象的高亮的字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField productName = highlightFields.get("productName");
            String newName = "";
            if (productName != null){
                //获取该高亮字段的高亮信息
                Text[] fragments = productName.getFragments();
                //将前缀、关键词、后缀进行拼接
                for (Text fragment : fragments) {
                    newName += fragment;
                }
            }
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //将高亮后的值替换掉旧值
            sourceAsMap.put("productName",newName);
            String json = JSON.toJSONString(sourceAsMap);
            ESProductTO esProductTO = JSON.parseObject(json, ESProductTO.class);
            esProductTOS.add(esProductTO);
        }
        return esProductTOS;
    }
}

编写测试代码:

    @Autowired
    private ESProductService esProductService;

    @Test
    public void testSearchHighLight() throws IOException {
        List<ESProductTO> products = esProductService.searchProduct("面");
        for (ESProductTO product : products) {
            log.info(product.toString());
        }
    }

日志查看:
在这里插入图片描述
可以看到,我们搜索的关键字 “面” 已经被高亮了!

猜你喜欢

转载自blog.csdn.net/qq_43750656/article/details/106752154