使用 annotated-text 字段编辑

annotated-text 会根据更常见的 text 字段(参见下面的“限制”)对文本内容进行分词,但也会将任何标记的注释标记直接注入到搜索索引中

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "annotated_text"
      }
    }
  }
}

这种映射允许将标记的文本(例如维基百科文章)索引为文本和结构化标记。注释使用类似 Markdown 的语法,使用一个或多个以 & 符号分隔的值的 URL 编码。

我们可以使用“_analyze” API 来测试示例注释如何在搜索索引中存储为标记

GET my-index-000001/_analyze
{
  "field": "my_field",
  "text":"Investors in [Apple](Apple+Inc.) rejoiced."
}

响应

{
  "tokens": [
    {
      "token": "investors",
      "start_offset": 0,
      "end_offset": 9,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "in",
      "start_offset": 10,
      "end_offset": 12,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "Apple Inc.", 
      "start_offset": 13,
      "end_offset": 18,
      "type": "annotation",
      "position": 2
    },
    {
      "token": "apple",
      "start_offset": 13,
      "end_offset": 18,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "rejoiced",
      "start_offset": 19,
      "end_offset": 27,
      "type": "<ALPHANUM>",
      "position": 3
    }
  ]
}

请注意,整个注释标记 Apple Inc. 作为单个标记放置在标记流中,并且与它注释的文本标记 (apple) 位于相同的位置(位置 2)。

现在,我们可以使用不分词提供的搜索值的常规 term 查询来搜索注释。注释是一种更精确的匹配方式,如本例所示,搜索 Beck 将不会匹配 Jeff Beck

# Example documents
PUT my-index-000001/_doc/1
{
  "my_field": "[Beck](Beck) announced a new tour"
}

PUT my-index-000001/_doc/2
{
  "my_field": "[Jeff Beck](Jeff+Beck&Guitarist) plays a strat"
}

# Example search
GET my-index-000001/_search
{
  "query": {
    "term": {
        "my_field": "Beck" 
    }
  }
}

除了将纯文本分词为单个单词(例如 beck)之外,我们还在标记流中与 beck 相同的位置注入单个标记值 Beck

请注意,注释可以在相同位置注入多个标记 - 在这里,我们同时注入了非常具体的 Jeff Beck 值和更广泛的术语 Guitarist。这使得更广泛的位置查询成为可能,例如查找 Guitarist 附近 strat 的提及。

使用这些精心定义的注释标记进行搜索的一个好处是,查询 Beck 不会匹配包含标记 jeffbeckJeff Beck 的文档 2。

在注释值中使用 = 符号(例如 [Prince](person=Prince))会导致文档被拒绝,并出现解析错误。将来,我们希望能够使用等号,因此今天将积极拒绝包含等号的文档。