文本分析概述
文本分析使 Elasticsearch 能够执行全文搜索,搜索结果会返回所有相关的结果,而不仅仅是完全匹配的结果。
如果你搜索"Quick fox jumps",你可能希望找到包含"A quick brown fox jumps over the lazy dog"的文档,你也可能希望找到包含相关词汇(如"fast fox"或"foxes leap")的文档。
分析通过分词实现全文搜索:将文本分解成更小的单元,称为词元。在大多数情况下,这些词元是单独的单词。
如果你将短语"the quick brown fox jumps"作为一个单一字符串进行索引,而用户搜索"quick fox",那么它不会被视为匹配。然而,如果你对短语进行分词并将每个单词分别索引,查询字符串中的术语就可以单独查找。这意味着它们可以通过搜索"quick fox""fox brown"或其他变体来匹配。
分词使得能够对单个术语进行匹配,但每个词元仍然会逐字匹配。这意味着:
• 搜索"Quick"不会匹配"quick",尽管你可能希望这两个词能够相互匹配。
• 尽管"fox"和"foxes"有相同的词根,但搜索"foxes"不会匹配"fox",反之亦然。
• 搜索"jumps"不会匹配"leaps"。尽管它们没有相同的词根,但它们是同义词,意思相近。
为了解决这些问题,文本分析可以将这些词元规范化为标准格式。这使得你可以匹配那些与搜索词不完全相同,但仍然足够相关的词元。例如:
• "Quick"可以转换为小写:"quick"。
• "foxes"可以进行词干提取,即还原为词根:"fox"。
• "jump"和"leap"是同义词,可以索引为同一个词:"jump"。
为了确保搜索词能够按预期匹配这些词,你可以对查询字符串应用相同的分词和规范化规则。例如,搜索"Foxes leap"可以被规范化为搜索"fox jump"。
自定义文本分析
文本分析是由分析器执行的,它是一组规则,控制整个分析过程。
Elasticsearch 包含一个默认的分析器,称为标准分析器,它在大多数情况下都能很好地工作。
如果你想定制搜索体验,你可以选择不同的内置分析器,甚至可以配置一个自定义的分析器。自定义分析器让你能够控制分析过程的每一步,包括:
• 在分词之前对文本进行更改。
• 文本如何转换为词元。
• 在索引或搜索之前对词元进行的规范化更改。
索引和搜索分析
文本分析发生在两个时间点:
索引时间
当文档被索引时,任何`text`字段的值都会被分析。
搜索时间
在对`text`字段执行全文搜索时,用户正在搜索的查询字符串(即用户输入的文本)会被分析。搜索时间也被称为查询时间。
在每个时间点使用的分析器(或分析规则集)分别被称为索引分析器或搜索分析器。
索引分析器和搜索分析器如何协同工作
在大多数情况下,索引和搜索时应该使用相同的分析器。这可以确保字段的值和查询字符串被转换成相同形式的标记(tokens)。反过来,这可以确保在搜索期间标记能够按预期匹配。
示例
一个文档在`text`字段中索引了以下值:
```
The QUICK brown foxes jumped over the dog!
```
字段的索引分析器将值转换为标记并对其进行规范化。在这个例子中,每个标记代表一个单词:
```
[ quick, brown, fox, jump, over, dog ]
```
然后这些标记被索引。
稍后,用户在同一个`text`字段中搜索以下内容:
用户期望这个搜索能够匹配之前索引的句子`The QUICK brown foxes jumped over the dog!`。
然而,查询字符串并不包含文档原始文本中使用的精确单词:
• `Quick`vs`QUICK`
• `fox`vs`foxes`
为了应对这种情况,查询字符串使用相同的分析器进行分析。这个分析器产生了以下标记:
为了执行搜索,Elasticsearch将这些查询字符串标记与`text`字段中索引的标记进行比较。
标记 查询字符串 `text`字段
`quick` X X
`brown` X
`fox` X X
`jump` X
`over` X
`dog` X
由于字段值和查询字符串以相同的方式进行了分析,它们产生了类似的标记。标记`quick`和`fox`是精确匹配的。这意味着搜索匹配了包含`"The QUICK brown foxes jumped over the dog!"`的文档,正如用户所期望的那样。
何时使用不同的搜索分析器
虽然不太常见,但在某些情况下,使用不同的索引和搜索分析器是有意义的。为此,Elasticsearch允许你为查询字符串指定一个单独的搜索分析器。
通常,只有在使用相同形式的标记对字段值和查询字符串进行匹配时会创建意外或不相关的搜索结果时,才应该指定一个单独的搜索分析器。
示例
Elasticsearch被用于创建一个搜索引擎,该引擎只匹配以提供的前缀开头的单词。例如,搜索`tr`应该返回`tram`或`trope`,但永远不会返回`taxi`或`bat`。
一个文档被添加到搜索引擎的索引中;该文档在`text`字段中包含一个这样的单词:
字段的索引分析器将值转换为标记并对其进行规范化。在这个例子中,每个标记代表一个可能的单词前缀:
```
[ a, ap, app, appl, apple]
```
然后这些标记被索引。
稍后,用户在同一个`text`字段中搜索以下内容:
用户期望这个搜索只匹配以`appli`开头的单词,例如`appliance`或`application`。搜索不应该匹配`apple`。
然而,如果使用字段的索引分析器来分析这个查询字符串,它会产生以下标记:
```
[ a, ap, app, appl, appli ]
```
当Elasticsearch将这些查询字符串标记与`apple`索引的标记进行比较时,它会找到多个匹配项。
标记 `appli` `apple`
`a` X X
`ap` X X
`app` X X
`appl` X X
`appli` X
这意味着搜索会错误地匹配`apple`。不仅如此,它还会匹配任何以`a`开头的单词。
为了解决这个问题,你可以为`text`字段的查询字符串指定一个不同的搜索分析器。
在这种情况下,你可以指定一个产生单个标记而不是一组前缀的搜索分析器:
这个查询字符串标记只会匹配以`appli`开头的单词的标记,这更符合用户的搜索期望。