基于 IKAnalyzer 实现 Elasticsearch 中文分词插件
虽然Elasticsearch有原生的中文插件elasticsearch-analysis-smartcn(实际上是lucence的org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer),但它似乎没能满足我的要求。比如我希望对文档中的“林夕”不分词(就是不要把它当成“林”,“夕”两个字索引),smartcn没法做到。
然后我找到了IK,以及elasticsearch-analysis-ik。elasticsearch-analysis-ik已经有些时候没人维护了。而且它使用的httpclient来获取分词词典。总之各种纠结。
最后,我决定还是自己写一个吧。
原来IKAnalyzer的目录结构
├── IKAnalyzer.cfg.xml ├── ext.dic ├── org │ └── wltea │ └── analyzer │ ├── cfg │ │ ├── Configuration.java │ │ └── DefaultConfig.java │ ├── core │ │ ├── AnalyzeContext.java │ │ ├── CJKSegmenter.java │ │ ├── CN_QuantifierSegmenter.java │ │ ├── CharacterUtil.java │ │ ├── IKArbitrator.java │ │ ├── IKSegmenter.java │ │ ├── ISegmenter.java │ │ ├── LetterSegmenter.java │ │ ├── Lexeme.java │ │ ├── LexemePath.java │ │ └── QuickSortSet.java │ ├── dic │ │ ├── DictSegment.java │ │ ├── Dictionary.java │ │ ├── Hit.java │ │ ├── main2012.dic │ │ └── quantifier.dic │ ├── lucene │ │ ├── IKAnalyzer.java │ │ └── IKTokenizer.java │ ├── query │ │ ├── IKQueryExpressionParser.java │ │ └── SWMCQueryBuilder.java │ ├── sample │ │ └── IKAnalyzerDemo.java │ └── solr │ └── IKTokenizerFactory.java └── stopword.dic
加入构建脚本
我发现没有使用任何的构建工具。我不是说不使用构建工具就是不好,而是我已经习惯了使用构建工具,不用就没有安全感。所以,我第一步是给它加构建脚本。
同时,我把原来的IKAnalyzerDemo.java改成两个测试类。最后运行测试,确保我的修改没有破坏原有逻辑
└── src ├── main │ ├── java │ │ └── ...... │ └── resources │ ├── IKAnalyzer.cfg.xml │ ├── main2012.dic │ ├── quantifier.dic │ └── stopword.dic └── test ├── java │ └── org │ └── wltea │ └── analyzer │ ├── IKAnalzyerTest.java │ └── LuceneIndexAndSearchTest.java └── resources ├── IKAnalyzer.cfg.xml ├── main2012.dic ├── quantifier.dic └── stopword.dic build.gradle apply plugin: 'java' //apply plugin: 'checkstyle' apply plugin: 'idea' sourceCompatibility = 1.7 version = '1.0' repositories { mavenCentral() } dependencies { compile( 'org.apache.lucene:lucene-core:4.10.4', 'org.apache.lucene:lucene-queryparser:4.10.4', 'org.apache.lucene:lucene-analyzers-common:4.10.4' ) testCompile group: 'junit', name: 'junit', version: '4.11' }
将项目拆成core和lucence两个子项目
我发现IK实际上由两部分组成:真正的分词逻辑和扩展Lucence分析器的逻辑。可以想象得到
我们需要支持不同版本的Lucence
我们可以把IK的分词逻辑应用到其它的搜索引擎上
基于这两点,我决定把原有的项目分成两个子项目。并加上测试:
├── build.gradle ├── ik-analyzer-core │ ├── build.gradle │ └── src │ ├── main │ │ ├── java │ │ │ └── ..... │ │ └── resources │ └── test ├── ik-analyzer-lucence │ ├── build.gradle │ └── src │ ├── main │ │ └── java │ │ └── org │ │ └── wltea │ │ └── analyzer │ │ ├── lucene │ │ │ ├── IKAnalyzer.java │ │ │ └── IKTokenizer.java │ │ └── query │ │ ├── IKQueryExpressionParser.java │ │ └── SWMCQueryBuilder.java │ └── test │ ├── java │ │ └── ..... └── settings.gradle
创建Elasticsearch插件
一开始,我还想让Elasticsearch插件只依赖core子项目就好了。谁知道要实现Elasticsearch的插件还需要依赖Lucence。所以Elasticsearch插件需要依赖lucence子项目。
实现的过程发现Elasticsearch的版本之间有些不同,你可以对比下: AnalysisIkPlugin.java和IKAnalyzerPlugin.java
目前,Elasticsearch文档中,关于它的插件的概念和原理说的都非常少!
├── build.gradle ├── ik-analyzer-core │ ├── ...... ├── ik-analyzer-elasticseaarch-plugin │ ├── build.gradle │ └── src │ └── main │ ├── java │ │ └── org │ │ └── elasticsearch │ │ └── plugin │ │ └── ikanalyzer │ │ ├── IKAnalyzerComponent.java │ │ ├── IKAnalyzerModule.java │ │ └── IKAnalyzerPlugin.java │ └── resources │ └── es-plugin.properties ├── ik-analyzer-lucence │ ├── ..... └── settings.gradle ## es-plugin.properties plugin=org.elasticsearch.plugin.ikanalyzer.IKAnalyzerPlugin
重构Core子项目
目前IK还有一个问题没有解决:灵活扩展现有的词典。比如我希望将“林夕”加入词典,从而使其不分被索引成“林”,“夕”。这样的应用场景非常多的。以至于elasticsearch-analysis-ik自己实现从远程读取词典的功能:Dictionary.java:338
但是我觉得这样还是够好。比如,我期望从本地的sqlite中读取词典呢?所以,我将IK原有的关于配置的读取的逻辑抽取出来:
/** * 加载主词典及扩展词典 */ private void loadMainDict(){ //建立一个主词典实例 _MainDict = new DictSegment((char)0); //读取主词典文件 InputStream is = this.getClass().getClassLoader().getResourceAsStream(cfg.getMainDictionary()); if(is == null){ throw new RuntimeException("Main Dictionary not found!!!"); } try { BufferedReader br = new BufferedReader(new InputStreamReader(is , "UTF-8"), 512); String theWord = null; do { theWord = br.readLine(); if (theWord != null && !"".equals(theWord.trim())) { _MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray()); } } while (theWord != null); } catch (IOException ioe) { System.err.println("Main Dictionary loading exception."); ioe.printStackTrace(); }finally{ try { if(is != null){ is.close(); is = null; } } catch (IOException e) { e.printStackTrace(); } } //加载扩展词典 this.loadExtDict(); }
其中cfg.getMainDictionary(),cfg是一个接口Configuration的实例,但是Dictionary假设getMainDictionary返回的一个文件的路径。所以,我认为这个接口的设计是没有意义的。
我们为什么不让cfg.getMainDictionary()直接返回Dictionary要求的词典内容呢,像这样:
/** * 加载主词典及扩展词典 */ private void loadMainDict() { //建立一个主词典实例 _MainDict = new DictSegment((char) 0); for (char[] segment : cfg.loadMainDictionary()) { _MainDict.fillSegment(segment); } }
这样,我们就可以实现像FileConfiguration,HttpConfiguraion,SqliteConfiguration,RedisConfiguration等任何你期望的扩展词典方式了。
但是,目前,我还没有实现任何的一种 :P
小结
实际上的重构和本文写的相差无几。还算比较顺利,要感谢原作者。这里,我还有一个问题没想通,就是如何打包才能让大家都方便用,比如方便在Elasticsearch中安装。希望大家能多给建议。
文章转载自 开源中国社区 [http://www.oschina.net]

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
前谷歌员工推出类 Spanner 数据库项目
斯宾塞·金博尔(Spencer Kimball)在离开谷歌之后,突然觉得不便,因为手头缺少了很多曾在公司内部使用的定制软件。于是,他携手其他谷歌离职者,决心打造自己的版本。现在,他们决心公开自己的工作成果,帮助有志者创办下一个谷歌或Facebook。 金博尔特别想打造属于自己的谷歌数据库系统Spanner。Spanner 的设计目的是为了与数以百万计数据库服务器上的数据打交道,该工具让谷歌的服务持 续在线,甚至在数个服务器甚至整个数据中心被关闭的情况下也是如此。少有公司需要运营如谷歌这般规模的数据中心,但系统的稳定性以及服务器间的资源负载均 衡自动化对大多数公司来说还是很有用的。 金博尔没有为谷歌Spanner项目工作过,但他在日常工作中用到过该项目。市面上目前没有类似项目存在,因此,他们决心打造自己的版本——CockroachDB。该项目是依据谷歌出版的关于Spanner的白皮书打造的开源数据库。 在去年2月推出后,CockroachDB很快便吸引到众多开发者参与,但项目进展不如预期。即便到了今天,项目仍然无法投入使用。因此,金博尔和其他8位开发者辞去工作,创办了Cockroach实...
- 下一篇
Apache 基金会宣布 Apache Eagle 成为顶级项目
2017年1月10日, 由超过350个开源项目及创新计划,全部由开发志愿者,治理志愿者及孵化志愿者组成的Apache软件基金会(ASF),宣布Apache Eagle已经从Apache孵化器项目毕业,正式升级成为顶级项目(TLP),这标志着该项目的社区和产品依照ASF精英管理的流程和原则顺利运作。 Apache Eagle是一个开源监视和警报解决方案,用于智能实时地识别大数据平台上的安全和性能问题,例如Apache Hadoop,Apache Spark等。 “我们很自豪Eagle能顺利度过孵化过程,并作为Apache顶级项目毕业”,Apache Eagle 副总裁张勇说,“社区正在积极改进产品,探讨并分析大型Hadoop集群中的各种性能和安全问题。” Eagle起源于eBay,最早用于解决大规模Hadoop集群的监控问题。 团队很快意识到这对整个社区也将很有用,所以于2015年10月将项目提交给Apache孵化器。从那时起,Eagle因为其广泛的使用场景,比如系统/服务监控,应用性能监控和安全漏洞检测,获得了开发人员和各种组织的注意。 Apache Eagle主要特点包括: 高可扩展...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程