使用Elasticsearch进行高效中文搜索
如果你使用过Elasticsearch,你就会知道分析和标记化是索引内容时最重要的步骤,如果没有它们,你的相关性就会很差,你的用户会不满意,你的结果也会很糟糕。
即使是英语内容,您也可能因为词干错误而失去相关性,或者因为没有进行适当的省略而错过一些文档,等等。如果你索引的是另一种语言,情况就更糟了;默认的分析程序不是万能的。
在处理中文文件时,即使只考虑中国的官方语言和世界上使用最多的普通话,一切都更加复杂。让我们深入研究中文内容标记化,并揭示使用Elasticsearch进行标记化的最佳方法。
中文搜索有什么难的?
汉字是符号,它们代表一个词或一个语素(语言的最小有意义的单位)。放在一起,它们的意思可以改变并代表一个全新的单词。另一个困难是单词和句子之间没有空格,这使得计算机很难知道单词的开始和结束位置。
中国有成千上万的汉字,即使在实践中,书面汉语也需要三四千人的知识。让我们来看一个例子:“volcano”这个词实际上是以下几个词的组合:
- 火
- 山的天空
我们的标记器必须足够聪明,以避免将这两个标识分开,因为当它们不在一起时,含义就会改变。
另一个困难是使用的拼写变体:
- 简体中文:书法;
- 繁体中文,更复杂、更丰富;書法;
- 拼音,一种罗马化的普通话形式;shūfǎ.
分析中文内容
在撰写本文时,以下是Elasticsearch可用的解决方案:
- 的默认的中国人分析仪基于Lucene 4中已弃用的类;
- 的paoding插件,遗憾的是没有维护,但基于非常好的词典;
- 的cjk分析仪这就形成了你的内容的双格图;
- 的智能汉语分析器,在官方支持的插件下发布;
- 最后是ICU插件和他的标记器.
这些分析仪非常不同,我们将用一个简单的测试词来比较它们的表现。
它的意思是“手机”,由两个符号组成,分别表示“手”和“机器”。这个符号也包含了很多其他的词:
- 机票
- 机器人
- 机枪
- 机会
我们的标记化不能分割这些标识,因为如果我搜索“手机”,我不想看到任何关于兰博拥有机关枪和看起来很坏的文件。
我们要用伟大的来测试我们的解决方案_analyze
API:
curl -XGET 'http://localhost:9200/chinese_test/_analyze?Analyzer =paoding_analyzer1' -d '
还有,我提过这个吗很棒的Elasticsearch小抄表了吗?
默认的中国人分析仪
在您的Elasticsearch实例中已经可用,这个分析器使用ChineseTokenizerLucene的类,它只将所有的标识符分隔成令牌。所以我们得到两个代币:手和机.
的Elasticsearch标准Analyzer产生完全相同的输出。出于这个原因,中国人已弃用,很快将被标准,你应该避免。
的paoding插件
Paoding是几乎一个行业标准,被称为优雅的解决方案。遗憾的是,Elasticsearch的插件没有维护,我只设法使它在1.0.1版本上工作,之后一些修改.下面是如何手动安装它:
git clone git@github.com:damienalexandre/elasticsearch-analysis- paodre .git /tmp/elasticsearch-analysis-paoding cd /tmp/elasticsearch-analysis-paoding mvn clean package sudo /usr/share/elasticsearch/bin/plugin -url file:/tmp/elasticsearch-analysis-paoding/target/releases/elasticsearch-analysis-paoding-1.2.2.zip -install elasticsearch-analysis-paoding #将所有dic配置文件复制到ES配置路径下-确保设置权限权限。ES需要写入/etc/elasticsearch/config/paoding!执行命令cp -r config/paoding /etc/elasticsearch/config/
在这个笨拙的安装过程之后(要在所有节点上完成),我们现在有了一个新的paodingTokenizer和两个收集器:max_word_len和most_word.默认情况下没有分析器是公开的,所以我们必须声明一个新的分析器:
PUT /chinese_test {"settings": {"number_of_shards": 1, "number_of_replicas": 0, "analysis": {"tokenizer": {"paoding1": {"type": "paoding", "collector": "most_word"}, "paoding2": {"type": "paoding", "collector": "max_word_len"}}, "analyzer": {"paoding_analyzer1": {"type": "custom", "tokenizer": "paoding1", "filter": ["standard"]}, "paoding_analyzer2": {"type": "custom", "tokenizer": "paoding2": {"type": "custom", "tokenizer": "paoding2": ["standard"]}}}}}
这两种配置都提供了良好的结果,具有干净和唯一的令牌。对于更复杂的句子,行为也很好。
的cjk分析仪
非常简单的分析器,它只将任何文本转换为双格图。“蝙蝠侠”变成了一串毫无意义的符号:Ba、at、tm、ma、an。对于亚洲语言,这个标记器是一个很好的非常简单的解决方案,但代价是更大的索引和有时不完全相关的结果。
在我们的例子中,只有两个词手机被索引了,看起来不错,但是如果我们用一个更长的词,比如元宵节(元宵节),产生两种代币:元宵和宵节,分别表示灯笼和小节日.
智能中文插件
非常容易安装感谢的家伙在Elasticsearch维护它:
Bin /plugin -install elasticsearch/elasticsearch-analysis-smartcn/2.3.0
它暴露了一个新的smartcn分析器,以及smartcn_tokenizer标记器,使用SmartChineseAnalyzerLucene。
它运行一个概率套件来找到一个最佳的词分离,使用隐马尔可夫模型和大量的训练文本。因此,已经嵌入了一个训练字典,它在普通文本上非常好——我们的例子被正确地标记了。
ICU插件
另一个官方插件。Elasticsearch支持“Unicode的国际组件”库。
Bin /plugin -install elasticsearch/elasticsearch-analysis-icu/2.4.1
这个插件是还建议如果您处理除英语以外的任何语言,我一直使用它来处理法语内容!
它暴露了icu_tokenizer我们将使用的Tokenizer,以及很多很棒的分析工具,比如icu_normalizer,icu_folding,icu_collation等。
它与中文和日文文本的字典一起工作,包含词频信息来推断符号组。在手机,一切都很好,工作如预期,但元宵节,生成两个令牌:元宵和节-那是因为灯笼和节日都比元宵节.
结果分解
分析仪 | (手机) | 元宵节(元宵节) | 元宵节与传统 |
---|---|---|---|
中国人 | [手] [机] | [元] [宵] [节] | [元] [宵] [節] |
paoding most_word | [手机] | [元宵] [元宵节] | [元宵] [節] |
paoding max_word_len | [手机] | [元宵节] | [元宵] [節] |
cjk | [手机] | [元宵] [宵节] | [元宵] [宵節] |
smartcn | [手机] | [元宵节] | [元宵] [節] |
icu_tokenizer | [手机] | [元宵] [节] | [元宵節] |
这些测试都是用Elasticsearch 1.3.2完成的,除了ES 1.0.1下的填充.
在我看来,paoding和smartcn得到最好的结果。的中国人Tokenizer是非常糟糕的icu_tokenizer是不是有点令人失望元宵节他的繁体字写得很好。
繁体中文支援
如引言所述,您可能需要处理来自文档或用户搜索请求的繁体中文。您需要一个规范化步骤来将这些传统输入翻译成现代中文,因为插件喜欢smartcn或paoding不能正确操作它。
您可以在应用程序中这样做,或者尝试在Elasticsearch中直接使用elasticsearch-analysis-stconvert插件。它可以将传统汉语和现代汉语中的单词进行双向转换。遗憾的是,您必须手动编译它,就像上面显示的填充插件一样。
最后一个解决方案是使用cjk:如果你不能正确地对输入进行标记,你仍然有很好的机会捕捉到你需要的文档,然后使用基于标记的信号来提高相关性icu_tokenizer这也很好。
用中文更进一步?
使用Elasticsearch进行分析时,无论处理的是什么内容,都没有完美的一刀切的解决方案,对于中文来说也是如此。您必须根据获得的信息编写并构建自己的分析器。例如,我要用cjk和smartcn标记化我的搜索字段,使用多领域和multi-match查询.
为了学习更多的中文,我建议Chineasy这是获得一些基本阅读技能的好方法!学习如此丰富的语言并不容易,你也应该阅读这篇文章在开始之前,这样你就知道你要做什么了!快乐编码!