写点什么

ElasticSearch 拼音搜索自定义扩展插件 (长拼音序列)

作者:alexgaoyh
  • 2023-03-31
    河南
  • 本文字数:2062 字

    阅读完需:约 7 分钟

  当前的中文搜索引擎都支持拼音搜索,但是在使用过程中会出现各种各样的场景,当前的自定义插件,用来处理在拼音搜索过程中如果遇到长拼音序列的情况,应该如何进行处理。

概述

  在进行拼音搜索的过程中,会有各种各样的输入方式,这些连续的拼音输入会形成一个长拼音序列,想进行正确的搜索,首要面对的一个问题是如何对一个长拼音序列进行切分。

拼音序列输入

  长拼音序列的划分会有很多种场景,这里简单描述几种常见的场景:


  1. 普通情况。

  2. 完整的、无错的、没有歧义的拼音序列,可以进行直接处理。

  3. 拼音缩写。

  4. 完全简写 :只输入拼音的首字母,较为常见。

  5. 先整后简 :前一个字是完整拼音,后一个字是拼音缩写。

  6. 先简后整 :比较少见,一般出现在想要使用「完全简写」的方式输入,但是发现匹配不到,因此再输入后一个字的完整拼音。


  在 ElasticSearch 中,有现有的拼音插件,支持不同版本的 ElasticSearch。经过分析,上述插件在遇到‘先整后简’、‘先简后整’的长序列,是无法搜索出来正常结果的,经过分析,如果找到一种方法,能够将长拼音序列进行切分,其实就可以满足结果。比如将 'wszgr'切分为 ‘w’、‘s’、‘z’、‘g’、‘r’,使用这个结果进行搜索,就把原问题进行了简化,仍使用上述的拼音插件就可以解决这个问题。


  综上所述,为了解决长拼音序列的搜索问题,就需要解决两个细分问题:1、拼音切分;2、Elasticsearch 自定义分词插件。

拼音切分

  先看如下的分词结果,使用的思路是类似在小学阶段学习的拼音表进行的实现,划分声母和韵母,然后根据规则进行切分,拼音序列的切分结果如下。


woszgr -> [wo, s, z, g, r]wszhonggren -> [w, s, zhong, g, ren]qianb -> [qian, b]qbi -> [q, bi]
复制代码


  中文拼音表中包含 23 个声母和 24 个韵母,进行组合可以得到大量的拼音序列,可以很容易得到所有的拼音序列,如下所示部分的拼音。


声母: b, p, m, f, d, t, n, l, g, k, h, j, q, x, zh, ch, sh, r, z, c, s, y, w韵母: a, o, e, i, u, ü, ai, ei, ui, ao, ou, iu, ie, üe, er, an, en, in, un, ün, ang, eng, ing, ong所有的拼音序列: ba, bo, bei, bu, bai, bei, bao, bi, bo, bu, bai, bei, bao, ban, ben, bin, bun, bang, beng, bing ……………………
复制代码

ElasticSearch 自定义分词插件

  这一部分,互联网上存在着大量的介绍,本章节不对其进行详细介绍,只把核心代码展示出来,详见源代码


public class PinyinCutAnalysisPlugin extends Plugin implements AnalysisPlugin {
public static String PLUGIN_NAME = "analysis-pycut";
@Override public Map<String, AnalysisModule.AnalysisProvider<TokenizerFactory>> getTokenizers() { Map<String, AnalysisModule.AnalysisProvider<TokenizerFactory>> extra = new HashMap<>(); extra.put("pycut_tokenizer", PinyinCutTokenizerFactory::getTokenizerFactory); return extra; }
@Override public Map<String, AnalysisModule.AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() { Map<String, AnalysisModule.AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> extra = new HashMap<>(); extra.put("pycut_analyzer", PinyinCutAnalyzerProvider::getAnalyzerProvider); return extra; }}
复制代码


  详情可见发行版地址,如果使用的是其他版本的 ElasticSearch,则 clone 源代码,更改 pom 文件中对应的 ElasticSearch 版本,重新进行 maven clean package 命令。

搜索示例

  第一段代码是 settings 配置,第二段代码是 mapping 配置。  使用如上配置的话,搜索 ’zguo‘、’zhongg‘、’zg‘ ,是都能匹配到 ’中国‘ 这个结果的。


{  "analysis": {    "analyzer": {      "pinyin_own_analyzer" : {        "tokenizer" : "pinyin_own_letter_tokenizer"      }    },    "tokenizer": {      "pinyin_own_letter_tokenizer": {        "type" : "pinyin",        "keep_first_letter": false,        "keep_separate_first_letter" : true,        "keep_full_pinyin" : true,        "keep_joined_full_pinyin": false,        "lowercase" : true,        "remove_duplicated_term" : true      }    }  }}
复制代码


{   "pyOwn": {      "type": "text",      "search_analyzer": "pycut_analyzer",      "analyzer": "pinyin_own_analyzer"   }}
复制代码

疑问

  在使用拼音插件的时候,如果遇到 ’zh‘、’ch‘、’sh‘ 这种声母,拼音插件返回的是’z‘、’c‘、’s‘,跟小学阶段学习到的结果不太一样,需要注意。


  本文所写的拼音扩展插件也由于上述的情况做了特殊的处理,即便拼音切分出来了 ’zh‘、’ch‘、’sh‘,分词的结果会更改为’z‘、’c‘、’s‘。

参考

  1. https://github.com/medcl/elasticsearch-analysis-pinyin

  2. https://github.com/OrangeX4/simple-pinyin

  3. https://gitee.com/alexgaoyh/elasticsearch-analysis-pinyincut


发布于: 刚刚阅读数: 4
用户头像

alexgaoyh

关注

DevOps 2013-12-08 加入

https://gitee.com/alexgaoyh

评论

发布
暂无评论
ElasticSearch 拼音搜索自定义扩展插件(长拼音序列)_中文分词_alexgaoyh_InfoQ写作社区