索引与搜索分析
文本分析发生在两个阶段:
索引时 | 索引文档时,所有文本字段的值都会被分析。 |
搜索时 | 对文本字段执行全文搜索时,查询字符串(用户输入的搜索文本)会被分析。搜索时也称为查询时(query time)。 |
在上述两个阶段所使用的分析器(或一组分析规则)分别称为索引分析器(index analyzer)和搜索分析器(search analyzer)。
索引分析器与搜索分析器如何协同工作
在大多数情况下,索引时和搜索时应使用相同的分析器。这能确保字段的值和查询字符串被转换为相同形式的词元,进而确保词元在搜索时按预期匹配。
示例
一个文档被索引,其某个文本字段的值为:
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对QUICKfox对foxes
为了解决这个问题,查询字符串会使用相同的分析器进行分析。该分析器产出以下词元:
[ quick, fox ]
执行搜索时,Elasticsearch 将这些查询字符串词元与文本字段中已索引的词元进行比较。
| 词元 | 查询字符串 | 文本字段 |
|---|---|---|
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。
向搜索引擎的索引添加一个文档;该文档的某个文本字段中包含这样一个单词:
"Apple"
该字段的索引分析器将这个值转换为词元并进行规范化。在本例中,每个词元代表该单词的一个潜在前缀:
[ a, ap, app, appl, apple]
这些词元随后被索引。
之后,用户在同一文本字段中搜索:
"appli"
用户期望这次搜索只匹配以 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 开头的单词。
要解决这个问题,可以为该文本字段上的查询字符串指定一个不同的搜索分析器。
在本例中,你可以指定一个产出单个词元而非一组前缀的搜索分析器:
[ appli ]
这样,这个查询字符串词元只会匹配以 appli 开头的单词的词元,更符合用户的搜索预期。