最近想为搜索引擎加上拼音搜索,在查阅网上信息之后找到两个插件,一个叫elasticsearch-analysis-pinyin (下文简称pinyin),另一个叫elasticsearch-analysis-lc-pinyin (下文简称lc-pinyin)。名字很相似,也就是后面多个lc。
pinyin是跟最火的中文分词插件ik同属一个项目组的。这款拼音分词插件同样是占据了市场的大多数。而lc-pinyin看起来对中文和拼音的混输支持的挺好,所以决定把两个都装上去试试了。
首先声明一下,我的elasticsearch版本是1.5.4。
pinyin分词测试
我首选的是pinyin,毕竟我已经用了ik,感觉他俩应该会比较般配。
pinyin的项目打开以后看到readme上面的文档说明也是挺详尽的,而对应我的es版本,似乎只能用最低的1.2版,几番对照之后安装了可以接受的最高版1.2.2,不得不说,这个版本下面的文档就差远了(也许功能也少点)。不过他提供的内容是挺多,一个analyzer,两个tokenizer和一个token-filter,这样就可以用它来搞各种自定义的拼音分词,比如配合nGram过滤器,还可以结合同义词过滤器等。比如结合nGram的效果:
PUT /test { "index" : { "analysis" : { "analyzer" : { "pinyin_analyzer" : { "tokenizer" : "my_pinyin", "filter" : ["standard","nGram"] } }, "tokenizer" : { "my_pinyin" : { "type" : "pinyin", "first_letter" : "prefix", "padding_char" : "" } } } } }
我们看一下他的分词效果:
执行http://localhost:9200/test/_analyze?text=刘德华&analyzer=pinyin_analyzer
{ "tokens": [ { "token": "l", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "ld", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "d", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "dh", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, …… { "token": "hu", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "u", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "ua", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 }, { "token": "a", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 } ] }
中间略去100+行,区区三个字,便搞出洋洋洒洒几十个分词,看起来也是有点蒙逼,而且“ua”这样的词也是有点鸡肋,谁会用“ua”搜“华”字呢,其实主要是nGram干的,我们还是上面的分词,去掉nGram过滤器就是下面的样子了:
{ "tokens": [ { "token": "ldhliudehua", "start_offset": 0, "end_offset": 3, "type": "word", "position": 1 } ] }
刘德华的拼音缩写加全拼,如此而已,而他的配置参数first_letter也只是决定前面ldh这个缩写出现的位置而已(例子中是prefix,即前缀)。
加了nGram的效果是太宽泛,而去掉则完全没有分词效果,那就先按下不表,我试试另一个吧。
lc-pinyin分词测试
其实内心对lc-pinyin有点喜欢,因为看了下面这一篇帖子中的演示效果是很合我心意的。
http://blog.csdn.net/chennanymy/article/details/52336368
而安装lc-pinyin也相对简单,因为只有两个选择,我安装了1.4.5版。
而装好之后也没什么花样,通过简单配置之后就有了lc_index和lc_search,一个用于创建索引,一个用于搜索。我们同样用上面的方式来测试分词效果:
执行http://localhost:9200/test/_analyze?text=刘德华&analyzer=lc_index
{ "tokens": [ { "token": "刘", "start_offset": 0, "end_offset": 1, "type": "word", "position": 1 }, { "token": "liu", "start_offset": 0, "end_offset": 1, "type": "word", "position": 1 }, { "token": "l", "start_offset": 0, "end_offset": 1, "type": "word", "position": 1 }, { "token": "德", "start_offset": 1, "end_offset": 2, "type": "word", "position": 2 }, { "token": "de", "start_offset": 1, "end_offset": 2, "type": "word", "position": 2 }, ……
这里我只粘贴了一半内容,我们可以看出,他做了简单的按中文字分词,然后保存了每个字的全拼和首字母。看起来就很干净简洁,而且这样支持中文混搜。混合搜索对我很有用,因为这个索引我是用于搜索引擎的输入框提示的,这种情况出现在用户已经输入了前面的一两个中文字,然后正在输入法中选后面的字的时候。比如我打“客厅”,我刚打完“客”,正在输打“厅”,这时输入框中就是“客ting”,这时无需用户继续在输入法中选择“厅”字,我已经可以给出“客厅”了。
小结
所以使用lc-pinyin,基本上可以零配置实现我要的效果了,这也是它的优势所在,不过你若想多一点自定义的东西,恐怕是很难实现的。
而pinyin的缺点也正是他有许多可自定义的东西,而且他的最新版有更多配置项,对于新手来说可能门槛略高,但是对于高手来说可以实现更多想要的东西。但不得不吐槽的是1.2.2版本的两个(也许还有更多,不过我没有在文档找到)配置项也是有点鸡肋,也或许是我不懂用吧,总之如果你的ES也是1.*版本就不推荐用pinyin了,除非你愿意花更多时间去探索他的隐藏关卡。