解决 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 需要索引位置信息和偏移量信息。高亮操作是在顶层文档执行的,对于嵌套文档来说,位置和偏移量信息是保存在嵌套文档中的,因此高亮操作无法访问这些信息。

同时,在顶层高亮嵌套文档会导致错误的结果,比如下面例子:

# 创建一个文档的 mapping
PUT t
{
  "mappings": {
    "t": {
      "properties": {
        "foo": {
          "type": "nested",
          "properties": {
            "text": {
              "type": "text"
            },
            "num": {
              "type": "integer"
            }
          }
        }
      }
    }
  }
}

# 插入数据
PUT t/t/1
{
  "foo": [
    {
      "text": "brown",
      "num": 1
    },
    {
      "text": "cow",
      "num": 2
    }
  ]
}

# 搜索结果
GET t/_search
{
  "query": {
    "nested": {
      "path": "foo",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "foo.text": "brown cow"
              }
            },
            {
              "match": {
                "foo.num": 1
              }
            }
          ]
        }
      }
    }
  },
  "highlight": {
    "fields": {
      "foo.text": {}
    }
  }
}

得到的高亮结果是 browncow ,然而 cow 是不应该是被高亮的。

但是通过 inner_hits 便可以得到正确的结果。

# 通过 inner_hits 进行搜索
GET t/_search
{
  "query": {
    "nested": {
      "path": "foo",
      "inner_hits": {      # 通过 inner_hits 进行搜索
        "_source": false,  # 不返回正文文本
        "highlight": {     # 高亮设置
          "fields": {
            "foo.text": {}
          }
        }
      },
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "foo.text": "brown cow"
              }
            },
            {
              "match": {
                "foo.num": 1
              }
            }
          ]
        }
      }
    }
  }
}

总结

对于嵌套文本来说,我们可以借助 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值