本书基于 Elasticsearch 2.x 版本,有些内容可能已经过时。
Unicode的世界
editUnicode的世界
edit当Elasticsearch在比较词元(token)的时候,它是进行字节(byte)级别的比较。 换句话说,如果两个词元(token)被判定为相同的话,他们必须是相同的字节(byte)组成的。然而,Unicode允许你用不同的字节来写相同的字符。
例如, é 和 é 的不同是什么?这取决于你问谁。对于Elasticsearch,第一个是由 0xC3 0xA9
这两个字节组成的,第二个是由 0x65
0xCC 0x81
这三个字节组成的。
对于Unicode,他们的差异和他们的怎么组成没有关系,所以他们是相同的。第一个是单个单词 é
,第二个是一个简单 e
和重音符 ´
。
如果你的数据有多个来源,就会有可能发生这种状况:因为相同的单词使用了不同的编码,导致一个形式的 déjà
不能和它的其他形式进行匹配。
幸运的是,这里就有解决办法。这里有4种Unicode 归一化形式 (normalization forms) : nfc
, nfd
, nfkc
, nfkd
,它们都把Unicode字符转换成对应标准格式,把所有的字符 进行字节(byte)级别的比较。
无论你选择哪一个归一化(normalization)模式,只要你的文本只用一种模式,那你的同一个词元(token)就会由相同的字节(byte)组成。例如,兼容 (compatibility) 模式 可以用连词 ffi
的简化形式 `ffi`来进行对比。
你可以使用 icu_normalizer
语汇单元过滤器(token filters) 来保证你的所有词元(token)是相同模式:
PUT /my_index { "settings": { "analysis": { "filter": { "nfkc_normalizer": { "type": "icu_normalizer", "name": "nfkc" } }, "analyzer": { "my_normalizer": { "tokenizer": "icu_tokenizer", "filter": [ "nfkc_normalizer" ] } } } } }
包括刚才提到过的 icu_normalizer
语汇单元过滤器(token filters)在内,这里还有 icu_normalizer
字符 过滤器(character filters)。虽然它和语汇单元过滤器做相同的工作,但是会在文本到达过滤器之前做。到底是用`standard` 过滤器,还是 icu_tokenizer
过滤器,其实并不重要。因为过滤器知道怎么来正确处理所有的模式。
但是,如果你使用不同的分词器,例如: ngram
, edge_ngram
, 或者 pattern
分词器,那么在语汇单元过滤器(token filters)之前使用 icu_normalizer
字符过滤器就变得有意义了。
通常来说,你不仅仅想要归一化(normalize)词元(token)的字节(byte)规则,还需要把他们转成小写字母。这个可以通过 icu_normalizer
和定制的归一化(normalization)的模式 nfkc_cf
来实现。下一节我们会具体讲这个。