PHP

使用Elasticsearch进行高效中文搜索

Damien亚历山大
分享

如果你使用过Elasticsearch,你就会知道分析和标记化是索引内容时最重要的步骤,如果没有它们,你的相关性就会很差,你的用户会不满意,你的结果也会很糟糕。

即使是英语内容,您也可能因为词干错误而失去相关性,或者因为没有进行适当的省略而错过一些文档,等等。如果你索引的是另一种语言,情况就更糟了;默认的分析程序不是万能的。

在处理中文文件时,即使只考虑中国的官方语言和世界上使用最多的普通话,一切都更加复杂。让我们深入研究中文内容标记化,并揭示使用Elasticsearch进行标记化的最佳方法。

标志(6)

汉字是符号,它们代表一个词或一个语素(语言的最小有意义的单位)。放在一起,它们的意思可以改变并代表一个全新的单词。另一个困难是单词和句子之间没有空格,这使得计算机很难知道单词的开始和结束位置。

中国有成千上万的汉字,即使在实践中,书面汉语也需要三四千人的知识。让我们来看一个例子:“volcano”这个词实际上是以下几个词的组合:

  • 山的天空

我们的标记器必须足够聪明,以避免将这两个标识分开,因为当它们不在一起时,含义就会改变。

另一个困难是使用的拼写变体:

  • 简体中文:书法
  • 繁体中文,更复杂、更丰富;書法
  • 拼音,一种罗马化的普通话形式;shūfǎ

分析中文内容

在撰写本文时,以下是Elasticsearch可用的解决方案:

这些分析仪非常不同,我们将用一个简单的测试词来比较它们的表现。
它的意思是“手机”,由两个符号组成,分别表示“手”和“机器”。这个符号也包含了很多其他的词:

  • 机票
  • 机器人
  • 机枪
  • 机会

我们的标记化不能分割这些标识,因为如果我搜索“手机”,我不想看到任何关于兰博拥有机关枪和看起来很坏的文件。

兰博

我们要用伟大的来测试我们的解决方案_analyzeAPI:

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_lenmost_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_normalizericu_foldingicu_collation等。

它与中文和日文文本的字典一起工作,包含词频信息来推断符号组。在手机,一切都很好,工作如预期,但元宵节,生成两个令牌:元宵-那是因为灯笼节日都比元宵节

结果分解

分析仪 (手机) 元宵节(元宵节) 元宵节与传统
中国人 [手] [机] [元] [宵] [节] [元] [宵] [節]
paoding most_word [手机] [元宵] [元宵节] [元宵] [節]
paoding max_word_len [手机] [元宵节] [元宵] [節]
cjk [手机] [元宵] [宵节] [元宵] [宵節]
smartcn [手机] [元宵节] [元宵] [節]
icu_tokenizer [手机] [元宵] [节] [元宵節]

这些测试都是用Elasticsearch 1.3.2完成的,除了ES 1.0.1下的填充

在我看来,paodingsmartcn得到最好的结果。的中国人Tokenizer是非常糟糕的icu_tokenizer是不是有点令人失望元宵节他的繁体字写得很好。

繁体中文支援

如引言所述,您可能需要处理来自文档或用户搜索请求的繁体中文。您需要一个规范化步骤来将这些传统输入翻译成现代中文,因为插件喜欢smartcnpaoding不能正确操作它。

您可以在应用程序中这样做,或者尝试在Elasticsearch中直接使用elasticsearch-analysis-stconvert插件。它可以将传统汉语和现代汉语中的单词进行双向转换。遗憾的是,您必须手动编译它,就像上面显示的填充插件一样。

最后一个解决方案是使用cjk:如果你不能正确地对输入进行标记,你仍然有很好的机会捕捉到你需要的文档,然后使用基于标记的信号来提高相关性icu_tokenizer这也很好。

用中文更进一步?

使用Elasticsearch进行分析时,无论处理的是什么内容,都没有完美的一刀切的解决方案,对于中文来说也是如此。您必须根据获得的信息编写并构建自己的分析器。例如,我要用cjksmartcn标记化我的搜索字段,使用多领域multi-match查询

为了学习更多的中文,我建议Chineasy这是获得一些基本阅读技能的好方法!学习如此丰富的语言并不容易,你也应该阅读这篇文章在开始之前,这样你就知道你要做什么了!快乐编码

Baidu