高亮

高亮 #

高亮用于在返回结果中标记命中的文本片段,提升可读性。Easysearch 在搜索阶段记录哪些文本片段匹配了查询,在返回阶段根据这些信息对原文做截取与包裹(例如 <em>...</em> 标签)。

基本用法 #

GET /articles/_search
{
  "query": {
    "match": { "content": "搜索 引擎" }
  },
  "highlight": {
    "fields": {
      "content": {}
    }
  }
}

返回结果中每条命中文档会包含 highlight 字段:

{
  "hits": {
    "hits": [
      {
        "_source": { "content": "Easysearch 是一款高性能的搜索引擎..." },
        "highlight": {
          "content": [
            "Easysearch 是一款高性能的<em>搜索</em><em>引擎</em>..."
          ]
        }
      }
    ]
  }
}

三种高亮器类型 #

Easysearch 支持三种高亮器,通过 type 参数指定:

类型说明优缺点
unified(默认)基于 Lucene Unified Highlighter,使用 BM25 对片段评分推荐首选。支持所有字段类型,性能与准确性平衡最佳
plain基于标准 Lucene Highlighter,逐词高亮小文本场景尚可,大文本或复杂查询时性能较差
fvhFast Vector Highlighter,需要 term_vector 设置为 with_positions_offsets大文本高亮最快,但需要额外索引存储

使用 FVH 高亮器 #

PUT /articles
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "term_vector": "with_positions_offsets"
      }
    }
  }
}
GET /articles/_search
{
  "query": {
    "match": { "content": "搜索 引擎" }
  },
  "highlight": {
    "type": "fvh",
    "fields": {
      "content": {}
    }
  }
}

常用参数 #

GET /articles/_search
{
  "query": {
    "match": { "content": "搜索 引擎" }
  },
  "highlight": {
    "pre_tags": ["<strong>"],
    "post_tags": ["</strong>"],
    "fields": {
      "content": {
        "fragment_size": 150,
        "number_of_fragments": 3,
        "no_match_size": 100
      },
      "title": {
        "number_of_fragments": 0
      }
    }
  }
}

参数速查 #

参数类型默认值说明
pre_tagsString[]["<em>"]高亮前标签
post_tagsString[]["</em>"]高亮后标签
fragment_sizeInteger100每个片段的字符数
number_of_fragmentsInteger5每字段返回的最大片段数。设为 0 返回整个字段
no_match_sizeInteger0无匹配时从字段开头返回的字符数
typeString"unified"高亮器类型:unifiedplainfvh
orderString-设为 "score" 按相关性排序片段
require_field_matchBooleantrue只高亮查询匹配到的字段
encoderString"default""default""html"(对 HTML 特殊字符编码)
highlight_queryObject-使用不同于搜索查询的查询来做高亮
boundary_scannerString"sentence"(unified)/ "chars"(plain/fvh)边界扫描器:charswordsentence
boundary_charsString".,!? \t\n"边界字符(与 chars 扫描器配合)
boundary_max_scanInteger20向前扫描边界字符的最大距离
boundary_scanner_localeStringLocale.ROOTword/sentence 扫描器配合使用的语言区域设置
fragmenterString"span"指定片段分割方式:span(按查询匹配位置分割)或 simple(按固定大小分割)。仅适用于 plain 高亮器
tags_schemaString-设为 "styled" 使用内置的 <em class="hltN"> 标签方案(N=1..10),替代自定义 pre_tags/post_tags
max_analyzed_offsetInteger1000000限制分析的最大字符偏移量。超过此值的文本不会被高亮。可在索引级通过 index.highlight.max_analyzed_offset 配置
phrase_limitInteger256FVH 考虑的最大短语数
force_sourceBooleanfalse强制从 _source 读取高亮文本
matched_fieldsString[]-FVH 专用:合并多个字段的匹配做高亮

多字段高亮 #

不同字段可以使用不同的高亮配置:

GET /articles/_search
{
  "query": {
    "multi_match": {
      "query": "分布式 搜索",
      "fields": ["title^3", "content"]
    }
  },
  "highlight": {
    "pre_tags": ["<mark>"],
    "post_tags": ["</mark>"],
    "fields": {
      "title": {
        "number_of_fragments": 0
      },
      "content": {
        "fragment_size": 200,
        "number_of_fragments": 3,
        "order": "score"
      }
    }
  }
}

title 设置 number_of_fragments: 0 表示返回整个字段内容并高亮,适合短字段。

使用自定义查询做高亮 #

有时你希望搜索和高亮使用不同的查询条件:

GET /articles/_search
{
  "query": {
    "bool": {
      "must": { "match": { "content": "搜索" } },
      "filter": { "term": { "status": "published" } }
    }
  },
  "highlight": {
    "fields": {
      "content": {
        "highlight_query": {
          "match": { "content": "搜索 引擎 分布式" }
        }
      }
    }
  }
}

性能考量 #

高亮不是免费的:

  • unified(默认)性能最好,适合大多数场景
  • fvh 对大文本最快,但需要 term_vector: with_positions_offsets,会增加索引大小约 30–50%
  • plain 对大文本性能最差,应避免在大文本字段上使用

建议:

  • 只对需要展示的字段做高亮,避免全字段高亮
  • 控制 fragment_sizenumber_of_fragments,避免返回过大的高亮结果
  • 对超长文本,考虑在建模时预先准备"摘要字段",在摘要上做高亮
  • 高并发场景优先使用 unified

常见问题 #

  • 匹配到结果但没有高亮:检查查询字段与高亮字段是否一致(如 content vs content.keyword),检查字段 analyzer 是否匹配
  • 高亮片段截断不理想:调整 fragment_size,或使用 boundary_scanner: "sentence" 按句子切分
  • 中文高亮分词不对:确保高亮字段和查询使用相同的分词器(如 IK 分词器)
  • HTML 标签被转义:使用 "encoder": "html" 对结果中的 HTML 特殊字符编码

小结 #

  • 高亮用于在返回结果中标记命中的文本片段,提升可读性
  • 三种高亮器:unified(推荐)、plainfvh(大文本最快)
  • 可以为不同字段配置不同的高亮选项
  • 控制高亮字段数量和片段大小,关注性能影响

下一步可以继续阅读:

参考手册(API 与参数) #