第三阶段 26 · highlight 高亮(返回命中片段)

📅 2026/8/3 17:09:38 👁️ 阅读次数 📝 编程学习
第三阶段 26 · highlight 高亮(返回命中片段)

26 · highlight 高亮(返回命中片段)

阶段:第三阶段补充 / 查询结果增强
ES:highlight| PostgreSQL:ts_headline()(全文检索高亮)


1. 概念

搜索结果里把命中的关键词用标签标出来(默认<em>...</em>),
前端渲染成高亮,就是highlight。它作用在参与打分的查询命中的字段上,
返回的是「带标记的片段(fragment)」,而不是整段原文。


2. PostgreSQL 对照

-- PG 全文检索的高亮:ts_headlineSELECTts_headline('english',description,to_tsquery('english','carbon'))FROMsalesdataWHEREto_tsvector('english',description)@@ to_tsquery('english','carbon');

ts_headline就是 PG 版的 highlight:把匹配词包成<b>...</b>并截取片段。


3. ES DSL

基本高亮

GET salesdata_idx/_search { "query": { "match": { "description": "carbon laptop" } }, "highlight": { "fields": { "description": {} } } }

返回里每个 hit 多一个highlight段:

"highlight":{"description":["super light <em>carbon</em> <em>laptop</em>"]}

自定义标签 + 片段控制

GET salesdata_idx/_search { "query": { "match": { "description": "carbon" } }, "highlight": { "pre_tags": ["<mark>"], "post_tags": ["</mark>"], "fragment_size": 120, // 每个片段长度 "number_of_fragments": 3, // 最多返回几个片段 "fields": { "description": {} } } }

多字段 + 整字段返回(不截断)

"highlight": { "fields": { "title": { "number_of_fragments": 0 }, // 0 = 返回整段并高亮,不切片 "description": { "fragment_size": 100 } } }

4. Spring Boot 实现

@ComponentpublicclassDoc26Highlight{@AutowiredprivateElasticsearchClientelasticsearchClient;/** 返回每条命中的高亮片段:Map<文档source, 高亮片段列表> */publicList<HighlightHit>search(StringindexName,Stringfield,Stringkeyword)throwsIOException{SearchResponse<Map>resp=elasticsearchClient.search(s->s.index(indexName).query(q->q.match(m->m.field(field).query(keyword))).highlight(h->h.preTags("<mark>").postTags("</mark>").fields(field,hf->hf.fragmentSize(120).numberOfFragments(3))),Map.class);List<HighlightHit>result=newArrayList<>();for(Hit<Map>hit:resp.hits().hits()){// 命中的高亮片段在 hit.highlight() 里,key 是字段名List<String>fragments=hit.highlight().getOrDefault(field,List.of());result.add(newHighlightHit(hit.source(),fragments));}returnresult;}publicrecordHighlightHit(Map<String,Object>source,List<String>fragments){}}

高亮片段不在_source里,而在hit.highlight()Map<String, List<String>>,key=字段名)。
import:co.elastic.clients.elasticsearch.core.search.Hit


5. 坑与最佳实践

  1. 高亮只对“参与查询的字段”生效highlight.fields里的字段要和 query 命中的字段对应,否则片段为空。
  2. filter上下文不高亮:filter 不算分、不记录命中位置;要高亮就把该条件放must/match
  3. keyword高亮意义有限:整串精确匹配没有“词”的概念,高亮通常给text字段用。
  4. number_of_fragments: 0返回整段并高亮(适合短标题);大文本用切片避免返回过长。
  5. 性能:高亮要重新分析字段内容,字段很大时开销明显;必要时用fvh(fast vector highlighter)+term_vector加速。

下一篇

28-collapse-字段折叠去重.md(列表去重),随后29-suggester-自动补全.md


← 上一篇:25-nested-嵌套对象与查询 | 总览 | 下一篇:27-pipeline-管道聚合 →