解决 Elastic Search 的 Fast Vector Highlighting (FVH) 策略无法高亮 nested 数据类型
前言
本文的目的不在介绍 ES 的三种高亮文本的策略,因此在阅读本文之前假设你已经
- 熟悉 ES 的使用
- 熟悉 ES 高亮的三种策略:Unified,Plain,FVH
- 需要对 nested field 的大文本进行高亮显示
提出问题
一般情况下,ES 的文本搜索结果高亮默认的策略是 Unified,这种高亮策略对于大部分文本是够用的,但是如果文本的长度比较长,比如达到几十兆甚至上百兆的文本数据,那么 ES 在 FETCH 阶段去解析文本并准备文本高亮的时候会非常耗时,并且很可能请求超时。从官网的文档中我们知道有一种 Fast Vector Highlighting (FVH) 策略,主要是针对大文本高亮准备的,也是一种典型的空间换时间的策略,但这需要我们文本属性的 term_vector
设置为 with_positions_offsets
。
不过,当一切准备就绪,而你的文本字段是 nested 数据类型的时候,确发现搜素出的结果中没有了 highlight 这一项。因此提出问题:FVH 策略如何高亮 nested field 的字段?
解决办法
FHV 需要索引位置信息和偏移量信息。高亮操作是在顶层文档执行的,对于嵌套文档来说,位置和偏移量信息是保存在嵌套文档中的,因此高亮操作无法访问这些信息。
同时,在顶层高亮嵌套文档会导致错误的结果,比如下面例子:
1 | # 创建一个文档的 mapping |
得到的高亮结果是 brown
和 cow
,然而 cow
是不应该是被高亮的。
但是通过 inner_hits
便可以得到正确的结果。
1 | # 通过 inner_hits 进行搜索 |
总结
对于嵌套文本来说,我们可以借助 inner_hits 和 FVH 来针对大文本进行快速的高亮显示。但是这也是一种通过空间换时间的做法,要针对具体的业务场景进行衡量选择。
参考文档
[1] Search your data » Highlighting https://www.elastic.co/guide/en/elasticsearch/reference/current/highlighting.html#highlighting
[2] Mapping parameters » term_vector https://www.elastic.co/guide/en/elasticsearch/reference/current/term-vector.html
[3] 白话Elasticsearch62-进阶篇之Highlighting高亮显示 https://cloud.tencent.com/developer/article/1862466
[4] ElasticSearch 高亮显示大文档搜索结果的策略和性能对比 https://cloud.tencent.com/developer/article/1491129
[5] Elastic Search: Highlighting Text That Contains HTML Tags https://hamidmosalla.com/2021/06/06/elastic-search-highlighting-text-that-contains-html-tags/
[6] FVH doesn’t highlight nested fields https://github.com/elastic/elasticsearch/issues/19265
[7] Elasticsearch highlight with nested objects https://stackoverflow.com/questions/15230580/elasticsearch-highlight-with-nested-objects