文本分析概念

edit

本节解释了Elasticsearch中文本分析的基本概念。

分析器的剖析

edit

一个分析器 —— 无论是内置的还是自定义的 —— 只是一个包含三个底层构建块的包:字符过滤器分词器词元过滤器

内置的 分析器 预先将这些构建块打包成适用于不同语言和文本类型的分析器。 Elasticsearch 还公开了各个构建块,以便它们可以组合起来定义新的 自定义 分析器。

字符过滤器

edit

一个字符过滤器接收原始文本作为字符流,并可以通过添加、删除或更改字符来转换流。例如,字符过滤器可以用于将阿拉伯-印度数字(٠‎١٢٣٤٥٦٧٨‎٩‎)转换为其阿拉伯-拉丁等效数字(0123456789),或者从流中去除HTML元素,如

一个分析器可以有零个或多个 字符过滤器,它们按顺序应用。

分词器

edit

一个分词器接收一个字符流,将其分解成单独的词元(通常是单个单词),并输出一个词元流。例如,一个空白分词器在看到任何空白时将文本分解成词元。它会将文本"Quick brown fox!"转换为词元[Quick, brown, fox!]

分词器还负责记录每个词项的顺序或位置,以及该词项所代表的原始单词的开始和结束字符偏移量

一个分析器必须有恰好一个 分词器

词元过滤器

edit

一个分词过滤器接收分词流,并可以添加、删除或更改分词。例如,一个lowercase分词过滤器将所有分词转换为小写,一个 stop分词过滤器移除常见词(停止词)如the从分词流中,以及一个 synonym分词过滤器将同义词引入分词流中。

Token filters 不允许改变每个token的位置或字符偏移量。

一个分析器可以有零个或多个 token filters,它们按顺序应用。

索引和搜索分析

edit

文本分析发生在两个时间点:

Index time
当文档被索引时,任何text字段值都会被分析。
Search time

当对一个文本字段运行全文搜索时, 查询字符串(用户正在搜索的文本)会被分析。

搜索时间也称为查询时间

每次使用的分析器或分析规则集分别称为索引分析器搜索分析器

索引和搜索分析器如何协同工作

edit

在大多数情况下,索引和搜索时应使用相同的分析器。这确保了字段值和查询字符串被转换为相同的令牌形式。反过来,这确保了在搜索过程中令牌能够按预期匹配。

示例

一个文档在一个文本字段中被索引为以下值:

The QUICK brown foxes jumped over the dog!

字段的索引分析器将值转换为标记并对其进行规范化。在这种情况下,每个标记代表一个单词:

[ quick, brown, fox, jump, over, dog ]

这些令牌随后被索引。

后来,用户在相同的文本字段中搜索:

"Quick fox"

用户期望这次搜索能匹配之前索引的句子, The QUICK brown foxes jumped over the dog!

然而,查询字符串并不包含文档原始文本中使用的精确词语:

  • Quick 对比 QUICK
  • fox 对比 foxes

为了解决这个问题,查询字符串使用相同的分析器进行分析。该分析器生成以下标记:

[ quick, fox ]

要执行搜索,Elasticsearch 会将这些查询字符串标记与 text 字段中索引的标记进行比较。

Token Query string text field

快速

X

X

棕色

X

狐狸

X

X

跳转

X

over

X

X

因为字段值和查询字符串以相同的方式进行了分析,它们生成了相似的词元。词元quickfox是完全匹配的。这意味着搜索匹配了包含"The QUICK brown foxes jumped over the dog!"的文档,正如用户所期望的那样。

何时使用不同的搜索分析器

edit

虽然不太常见,但在某些情况下,在索引和搜索时使用不同的分析器是有意义的。为此,Elasticsearch允许您指定一个单独的搜索分析器

通常情况下,只有在使用相同形式的标记进行字段值和查询字符串时,会产生意外或不相关的搜索匹配时,才应指定单独的搜索分析器。

示例

Elasticsearch 用于创建一个搜索引擎,该引擎仅匹配以提供的前缀开头的单词。例如,搜索 tr 应返回 tramtrope——但绝不会返回 taxibat

一个文档被添加到搜索引擎的索引中;该文档在一个文本字段中包含这样一个词:

"Apple"

字段的索引分析器将值转换为标记并对其进行规范化。在这种情况下,每个标记都代表该词的一个潜在前缀:

[ a, ap, app, appl, apple]

这些令牌随后被索引。

后来,用户在相同的文本字段中搜索:

"appli"

用户期望此搜索仅匹配以appli开头的单词,例如applianceapplication。搜索不应匹配apple

然而,如果使用索引分析器来分析这个查询字符串,它将产生以下标记:

[ a, ap, app, appl, appli ]

当Elasticsearch将这些查询字符串标记与为apple索引的标记进行比较时,它会找到多个匹配项。

Token appli apple

a

X

X

ap

X

X

app

X

X

appl

X

X

appli

X

这意味着搜索会错误地匹配apple。不仅如此,它还会匹配任何以a开头的单词。

要解决这个问题,您可以为在text字段上使用的查询字符串指定一个不同的搜索分析器。

在这种情况下,您可以指定一个生成单个词元的搜索分析器,而不是一组前缀:

[ appli ]

此查询字符串标记将仅匹配以 appli开头的单词的标记,这更符合用户的搜索预期。

词干提取

edit

词干提取是将一个单词缩减为其词根形式的过程。这确保了在搜索过程中单词的变体能够匹配。

例如,walkingwalked 可以被词干提取为相同的词根: walk。一旦被词干提取,这两个词中的任何一个在搜索中都会匹配另一个。

词干提取是依赖于语言的,但通常涉及从单词中去除前缀和后缀。

在某些情况下,词干化后的词根可能不是一个真实的词。例如,jumpingjumpiness 都可以被词干化为 jumpi。虽然 jumpi 不是一个真实的英语单词,但这对于搜索来说并不重要;如果一个词的所有变体都被简化为相同的词根形式,它们将会正确匹配。

词干提取器令牌过滤器

edit

在Elasticsearch中,词干提取由词干器分词过滤器处理。这些分词过滤器可以根据它们提取词干的方式进行分类:

因为词干提取会改变词元,我们建议在索引和搜索分析期间使用相同的词干提取器词元过滤器。

算法词干提取器

edit

算法词干提取器对每个单词应用一系列规则,将其简化为词根形式。例如,英语的算法词干提取器可能会去除复数单词末尾的-s-es后缀。

算法词干提取器有一些优势:

  • 它们几乎不需要设置,通常开箱即用。
  • 它们占用很少的内存。
  • 它们通常比字典词干提取器更快。

然而,大多数算法词干提取器仅改变单词的现有文本。这意味着它们可能无法很好地处理不规则单词,这些单词不包含其词根形式,例如:

  • be, are, 和 am
  • mousemice
  • footfeet

以下标记过滤器使用算法词干提取:

  • stemmer,为多种语言提供算法词干提取,其中一些语言有额外的变体。
  • kstem,一种结合了算法词干提取和内置词典的英语词干提取器。
  • porter_stem,我们推荐的英语算法词干提取器。
  • snowball,使用基于Snowball的词干提取规则为多种语言提供支持。

字典词干提取器

edit

字典词干提取器在提供的字典中查找单词,将未词干化的单词变体替换为字典中的词干化单词。

理论上,字典词干提取器非常适合用于:

  • 词干提取不规则单词
  • 辨别拼写相似但概念上无关的词语,例如:

    • organorganization
    • brokerbroken

在实践中,算法词干提取器通常优于字典词干提取器。这是因为字典词干提取器具有以下缺点:

  • 字典质量
    字典词干提取器的质量取决于其字典。为了表现良好,这些字典必须包含大量词汇,定期更新,并随语言趋势变化。通常,当一个字典发布时,它可能已经不完整,并且其中的一些条目已经过时。
  • 大小和性能
    字典词干提取器必须将其字典中的所有单词、前缀和后缀加载到内存中。这可能会占用大量内存。低质量的字典在处理前缀和后缀移除时也可能效率较低,这会显著减慢词干提取过程。

您可以使用 hunspell 分词过滤器来执行字典词干提取。

如果可用,我们建议在尝试使用 hunspell 分词过滤器之前,先尝试使用您语言的算法词干提取器。

控制词干提取

edit

有时词干提取会产生拼写相似但概念上无关的共享根词。例如,词干提取器可能会将 skiesskiing 都简化为相同的根词:ski

为了防止这种情况并更好地控制词干提取,您可以使用以下令牌过滤器:

  • stemmer_override,它允许你定义特定词干的规则。
  • keyword_marker,它将指定的标记标记为关键字。关键字标记不会被后续的词干化标记过滤器处理。
  • conditional,它可以用来将标记标记为关键字,类似于keyword_marker过滤器。

对于内置的语言分析器,您还可以使用 stem_exclusion参数来指定一个不会被词干化的单词列表。

代币图表

edit

当一个分词器将文本转换为一系列标记时,它还会记录以下内容:

  • 每个标记在流中的位置
  • 标记跨越的位置长度,即标记跨越的位置数量

使用这些,您可以创建一个 有向无环图, 称为令牌图,用于一个流。在令牌图中,每个位置代表一个节点。每个令牌代表一条边或弧,指向下一位置。

token graph qbf ex

同义词

edit

一些 token filters 可以向现有的 token 流中添加新的 tokens,例如同义词。这些同义词通常与现有 tokens 占据相同的位置。

在下面的图中,quick 及其同义词 fast 的位置都是 0。它们占据了相同的位置。

token graph qbf synonym ex

多位置令牌

edit

一些标记过滤器可以添加跨越多个位置的标记。这些可以包括多词同义词的标记,例如使用“atm”作为“自动取款机”的同义词。

然而,只有一些标记过滤器,称为图标记过滤器,能够准确记录多位置标记的positionLength。这些过滤器包括:

一些分词器,例如 nori_tokenizer,也能够准确地将复合词分解为多位置词。

在下面的图中,域名系统 及其同义词 dns 都具有 0 的位置。然而,dnspositionLength3。图中的其他标记的默认 positionLength1

token graph dns synonym ex

使用令牌图进行搜索

edit

索引忽略positionLength属性,并且不支持包含多位置标记的标记图。

然而,像matchmatch_phrase这样的查询,可以使用这些图表从单个查询字符串生成多个子查询。

示例

用户使用match_phrase查询对以下短语进行搜索:

域名系统是脆弱的

搜索分析期间,dnsdomain name system的同义词)被添加到查询字符串的标记流中。dns标记的positionLength3

token graph dns synonym ex

The match_phrase query 使用此图表为以下短语生成子查询:

dns is fragile
domain name system is fragile

这意味着查询匹配包含以下任一内容的文档:dns is fragile domain name system is fragile

无效的令牌图

edit

以下标记过滤器可以添加跨越多个位置的标记,但仅记录默认的positionLength1

这意味着这些过滤器将对包含此类令牌的流生成无效的令牌图。

在下面的图中,dnsdomain name system 的多位置同义词。然而,dns 的默认 positionLength 值为 1,导致图表无效。

token graph dns invalid ex

避免使用无效的令牌图进行搜索。无效的图可能导致意外的搜索结果。