如果有口音 | Elasticsearch: 权威指南 | Elastic
2024-12-21
英语用变音符号(例如 ´
, ^
, 和 ¨
) 来强调单词—例如 rôle
, déjà
, 和 däis
—但是是否使用他们通常是可选的.
其他语言则通过变音符号来区分单词。当然,只是因为在你的索引中拼写正确的单词并不意味着用户将搜索正确的拼写。
去掉变音符号通常是有用的,让 rôle
对应 role
, 或者反过来。 对于西方语言,可以用 asciifolding
字符过滤器来实现这个功能。 实际上,它不仅仅能去掉变音符号。它会把Unicode字符转化为ASCII来表示:
ß
⇒ ss
æ
⇒ ae
ł
⇒ l
ɰ
⇒ m
⁇
⇒ ??
❷
⇒ 2
⁶
⇒ 6
像 lowercase
过滤器一样, asciifolding
不需要任何配置,可以被 custom
分析器直接使用:
PUT /my_index { "settings": { "analysis": { "analyzer": { "folding": { "tokenizer": "standard", "filter": [ "lowercase", "asciifolding" ] } } } } } GET /my_index?analyzer=folding My œsophagus caused a débâcle
理所当然的,去掉变音符号会丢失原意。 例如, 参考 这三个 西班牙单词:
esta
ésta
esta
的古代用法.
está
通常我们会合并前两个形式的单词,而去区分和他们不相同的第三个形式的单词。类似的:
sé
se
不幸的是,没有简单的方法,去区分哪些词应该保留变音符号和哪些词应该去掉变音符号。而且很有可能,你的用户也不知道.
相反, 我们对文本做两次索引: 一次用原文形式,一次用去掉变音符号的形式 :
PUT /my_index/_mapping/my_type { "properties": { "title": { "type": "string", "analyzer": "standard", "fields": { "folded": { "type": "string", "analyzer": "folding" } } } } }
你可以使用 analyze
API 分析 Esta está loca (This woman is crazy)这个句子,来验证字段映射:
GET /my_index/_analyze?field=title Esta está loca GET /my_index/_analyze?field=title.folded Esta está loca
可以用更多的文档来测试:
PUT /my_index/my_type/1 { "title": "Esta loca!" } PUT /my_index/my_type/2 { "title": "Está loca!" }
现在,我们可以通过联合所有的字段来搜索。在multi_match`查询中通过 <<most-fields,`most_fields
mode>> 模式来联合所有字段的结果:
GET /my_index/_search { "query": { "multi_match": { "type": "most_fields", "query": "esta loca", "fields": [ "title", "title.folded" ] } } }
通过 validate-query
API 来执行这个查询可以帮助你理解查询是如何执行的:
GET /my_index/_validate/query?explain { "query": { "multi_match": { "type": "most_fields", "query": "está loca", "fields": [ "title", "title.folded" ] } } }
multi-match
查询会搜索在 title
字段中原文形式的单词 (está
),和在 title.folded
字段中去掉变音符号形式的单词 esta
:
(title:está title:loca ) (title.folded:esta title.folded:loca)
无论用户搜索的是 esta
还是 está
; 两个文档都会被匹配,因为去掉变音符号形式的单词在
title.folded
字段中。然而,只有原文形式的单词在 title
字段中。此额外匹配会把包含原文形式单词的文档排在结果列表前面。
我们用 title.folded
字段来 扩大我们的网 (widen the net)来匹配更多的文档,然后用原文形式的 title
字段来把关联度最高的文档排在最前面。在可以为了匹配数量牺牲文本原意的情况下,这个技术可以被用在任何分析器里。
asciifolding
过滤器有一个叫做 preserve_original
的选项可以让你这样来做索引
,把词的原文词元(original token)和处理--折叠后的词元(folded token)放在同一个字段的同一个位置。开启了这个选项,结果会像这样:
Position 1 Position 2 -------------------------- (ésta,esta) loca --------------------------
虽然这个是节约空间的好办法,但是也意味着没有办法再说“给我精确匹配的原文词元”(Give me an exact match on the original word)。包含去掉和不去掉变音符号的词元,会导致不可靠的相关性评分。
所以,正如我们这一章做的,把每个字段的不同形式分开到不同的字段会让索引更清晰。
官方地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/asciifolding-token-filter.html