如何通过Elasticsearch实现搜索的关键词达到高亮的效果

高亮

首先介绍一下什么是搜索的关键词达到高亮的效果,如图所示

当在百度里面搜索elasticsearch 的时候,可以看到出现的搜索结果里面elasticsearch 这个关键词明显与其他的条文不一样,用红颜色凸显了"高亮效果"。当我们想要在自己的项目里面也实现相同的高亮效果,可以借助ES来帮助我们实现。

通过ES实现高亮效果

现在有一个场景:输入相关的面试题题目返回的结果中题目出现高亮效果,类似这样的效果

那么后端的逻辑应该怎么写呢?(只说明核心逻辑)

首先在查询ES的时候就设置好相应的高亮属性

dart 复制代码
    private EsSearchRequest createSearchListQuery(SubjectInfoES req){
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
		
		//构造查询条件-根据题目名字查询
        MatchQueryBuilder matchNameQueryBuilder =
                QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_NAME,req.getSubjectName());
        boolQueryBuilder.should(matchNameQueryBuilder);
        //设置优先级
        matchNameQueryBuilder.boost(2);

		//其他的代码逻辑...

        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("+").requireFieldMatch(false);
        highlightBuilder.preTags("<span style = \"color:red\">");
        highlightBuilder.postTags("</span>");

        //设置高亮和条件
        esSearchRequest.setHighlightBuilder(highlightBuilder);
        esSearchRequest.setBoolQueryBuilder(boolQueryBuilder);
		
		//其他的代码逻辑...

        return esSearchRequest;
    }

这里通过
HighlightBuilder highlightBuilder = new HighlightBuilder().field("+").requireFieldMatch(false);

构造了一个ES的高亮器

在这里,field("+") 表示要对所有字段进行高亮处理
requireFieldMatch(false) 表示不需要确切字段匹配,即如果任何字段中包含查询的关键字 ,都会被高亮显示

如果设置为requireFieldMatch(true)的话 即查询出来的字段中要完全包含查询的关键字才会被高亮处理

java 复制代码
        highlightBuilder.preTags("<span style = \"color:red\">");
        highlightBuilder.postTags("</span>");

这两段代码的意思是要实现高亮的字段在返回给前端的时候会被"<span style = \"color:red\">""</span>"囊括起来,举个例子:<span style = \"color:red\"> elasticsearch倒排索引为什么快 </span>

java 复制代码
        //设置高亮和条件
        esSearchRequest.setHighlightBuilder(highlightBuilder);
        esSearchRequest.setBoolQueryBuilder(boolQueryBuilder);

这两段代码的作用是设置搜索关键词实现高亮和实现高亮的关键词是哪些关键词

在设置好高亮的相关条件以后,就得从ES中查询相关的数据了并且处理相关的数据

java 复制代码
    public PageResult<SubjectInfoES> querySubjectList(SubjectInfoES req) {
		PageResult<SubjectInfoES> pageResult = new PageResult<>();
		//设置相关条件
        EsSearchRequest esSearchRequest = createSearchListQuery(req);
        //搜索
        SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(),esSearchRequest);

        //获取Elasticsearch搜索响应中包含的搜索结果
        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] hits = searchHits.getHits();
        //遍历响应结果
        for (SearchHit hit : hits) {
            //将ES返回的结果映射到返回的实体中的代码....
			
			//开始处理高亮
			
			//高亮的字段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();

        //处理name的高亮字段
        HighlightField nameHighlightField = highlightFields.get(EsSubjectFields.SUBJECT_NAME);
        if (ObjectUtils.isNotEmpty(nameHighlightField)){
            Text[] fragments = nameHighlightField.fragments();
            StringBuilder stringBuilder = new StringBuilder();
            for (Text fragment : fragments){
                stringBuilder.append(fragment.string());
            }
            result.setSubjectName(stringBuilder.toString());
        }
        //处理内容中的高亮字段
        HighlightField answerHighlightField = highlightFields.get(EsSubjectFields.SUBJECT_ANSWER);
        if (ObjectUtils.isNotEmpty(answerHighlightField)){
            Text[] fragments = answerHighlightField.fragments();
            StringBuilder stringBuilder = new StringBuilder();
            for (Text fragment : fragments){
                stringBuilder.append(fragment.string());
            }
            result.setSubjectAnswer(stringBuilder.toString());
        }
            
            //将ES返回的结果映射到返回的实体中的代码....
        }

		//其他的代码逻辑

        return pageResult;
    }

这段代码展现了如何处理高亮,核心代码实际上是这一段

java 复制代码
        //高亮的字段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();

        //处理name的高亮字段
        HighlightField nameHighlightField = highlightFields.get(EsSubjectFields.SUBJECT_NAME);
        if (ObjectUtils.isNotEmpty(nameHighlightField)){
            Text[] fragments = nameHighlightField.fragments();
            StringBuilder stringBuilder = new StringBuilder();
            for (Text fragment : fragments){
                stringBuilder.append(fragment.string());
            }
            result.setSubjectName(stringBuilder.toString());
        }

首先调用hit.getHighlightFields()方法返回一个包含文档中高亮字段的映射,然后从高亮字段映射中获取名为 "SUBJECT_NAME" 的高亮字段(也就是题目名字),从高亮字段中提取相关的文本片段,fragments() 方法返回一个 Text 对象数组,每个 Text 对象表示高亮字段中的一个文本片段。

这里解释一下:

现在假设用户搜索了关键词 "Elasticsearch",而搜索结果中包含了一篇文章的标题和摘要,其中标题和摘要分别是两个字段。搜索结果如下:

标题:Introduction to Elasticsearch

如果我们对标题和摘要字段都进行了高亮处理,那么可能会得到以下的高亮结果:

高亮标题:Introduction to <span style="background-color: yellow;"> Elastic </span>search

这个时候fragment(段落)的内容是Introduction to <span style="background-color: yellow;"> Elastic </span>search

最后将每个高亮的文本拼接成一个完整的字符串并存储在结果对象的相应属性中,交给前端进行相应的处理,前端可以使用 HTML 和 CSS 来展示高亮文本,通常会将匹配的关键词用特殊样式标记(例如使用 标签添加背景颜色),以使用户能够直观地看到匹配的部分,最后实现高亮效果。

相关推荐
LaughingZhu6 小时前
Product Hunt 每日热榜 | 2026-02-14
数据库·人工智能·经验分享·神经网络·搜索引擎·chatgpt
欧恩意6 小时前
【Tools】Java反汇编工具推荐
java·汇编
寻星探路7 小时前
【JVM 终极通关指南】万字长文从底层到实战全维度深度拆解 Java 虚拟机
java·开发语言·jvm·人工智能·python·算法·ai
Elastic 中国社区官方博客7 小时前
DevRel 通讯 — 2026 年 2 月
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·jina
lbb 小魔仙7 小时前
【Java】Java 实战项目:手把手教你写一个电商订单系统
android·java·python
星河耀银海7 小时前
Java安全开发实战:从代码防护到架构安全
java·安全·架构
青云交7 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市水资源管理与节水策略制定中的应用
java·java 大数据·java 大数据可视化·城市水资源管理·spark 数据清洗·echarts 热力图·管网漏损控制
紫陌涵光7 小时前
112. 路径总和
java·前端·算法
workflower7 小时前
多变量时间序列预测
java·hadoop·nosql·需求分析·big data·结对编程
Volunteer Technology8 小时前
DynamicTP动态线程池(四)
java·spring boot·后端·spring