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. 坑与最佳实践
- 高亮只对“参与查询的字段”生效:
highlight.fields里的字段要和 query 命中的字段对应,否则片段为空。 filter上下文不高亮:filter 不算分、不记录命中位置;要高亮就把该条件放must/match。keyword高亮意义有限:整串精确匹配没有“词”的概念,高亮通常给text字段用。number_of_fragments: 0返回整段并高亮(适合短标题);大文本用切片避免返回过长。- 性能:高亮要重新分析字段内容,字段很大时开销明显;必要时用
fvh(fast vector highlighter)+term_vector加速。
下一篇
28-collapse-字段折叠去重.md(列表去重),随后29-suggester-自动补全.md。
← 上一篇:25-nested-嵌套对象与查询 | 总览 | 下一篇:27-pipeline-管道聚合 →