在中文分词器中, IKAnalyzer 作的是相对不错的,有着细度分割和智能使用两个模式 。
可是,这个版本由于太陈旧,做者再也不维护,(项目估计是。。。),因此与如今的Lucene 6.6 版本差距有些大。因此,我就根据网上各位大神的文章,加上本身对 API 与源码的阅读,稍微的进行了改动,能够简单的运行。
注: 这里的简单是指,能够简单的运行源码 中的简单案例。git
IKAnaylzer版本: IK Analyzer 2012FFgithub
感谢提供的分词源码 http://git.oschina.net/wltea/...数组
lucene 版本:lucene 6.60iphone
源码ide
/** * Lucene 4.0 Tokenizer适配器类构造函数 * @param in * @param useSmart */ public IKTokenizer(Reader in, boolean useSmart) { super(in); offsetAtt = addAttribute(OffsetAttribute.class); termAtt = addAttribute(CharTermAttribute.class); typeAtt = addAttribute(TypeAttribute.class); _IKImplement = new IKSegmenter(input, useSmart); }
经查阅 lucene 源码
Tokenizer类的构造器已经再也不接收 Reader 源码以下函数
protected Tokenizer() { this.input = ILLEGAL_STATE_READER; this.inputPending = ILLEGAL_STATE_READER; } protected Tokenizer(AttributeFactory factory) { super(factory); this.input = ILLEGAL_STATE_READER; this.inputPending = ILLEGAL_STATE_READER; }
所以改动 IKTokenizer 类 ,以下学习
public IKTokenizer( boolean useSmart) { super(); offsetAtt = addAttribute(OffsetAttribute.class); termAtt = addAttribute(CharTermAttribute.class); typeAtt = addAttribute(TypeAttribute.class); //传入 IKSegmenter 的 input Reader 流,会被 父类 Tokenizer 类的无参构造器 //初始化为 this.input = ILLEGAL_STATE_READER; _IKImplement = new IKSegmenter(input, useSmart); }
去除了 Reader 形参 。 默认调用 父类 的 无参构造函数 Tokenizer()
注:在该博客下发现,还须要配置分词器工厂类,所以还要多增长一段构造器代码,以下测试
//方便建立 工厂类 public IKTokenizer(AttributeFactory factory, boolean useSmart) { super(factory); offsetAtt = addAttribute(OffsetAttribute.class); termAtt = addAttribute(CharTermAttribute.class); typeAtt = addAttribute(TypeAttribute.class); _IKImplement = new IKSegmenter(input, useSmart); }
源码ui
/** * 重载Analyzer接口,构造分词组件 */ @Override protected TokenStreamComponents createComponents(String fieldName, final Reader in) { Tokenizer _IKTokenizer = new IKTokenizer(in, this.useSmart()); return new TokenStreamComponents(_IKTokenizer); }
lucene 6.6 关于 Analyzer 接口中 关于 createComponents() 方法的源码this
protected abstract Analyzer.TokenStreamComponents createComponents(String var1);
结合上文中对 IKTokenizer 源码的改动,所以须要去除 参数 Reader in
改动的代码 以下:
/** * 重载Analyzer接口,构造分词组件 */ @Override protected TokenStreamComponents createComponents(String fieldName) { Tokenizer _IKTokenizer = new IKTokenizer(this.useSmart()); return new Analyzer.TokenStreamComponents(_IKTokenizer); }
源码以下:
// 借助lucene queryparser 生成SWMC Query QueryParser qp = new QueryParser(Version.LUCENE_43, fieldName, new StandardAnalyzer( Version.LUCENE_43)); qp.setDefaultOperator(QueryParser.AND_OPERATOR); qp.setAutoGeneratePhraseQueries(true);
因为新版本的 lucene 已经不在使用 Version 类 进行定义,(个人上一篇lucene6.6 学习心得说的很清楚)所以须要将之移除。
移除后,改动版本以下:
//借助lucene queryparser 生成SWMC Query QueryParser qp = new QueryParser(fieldName, new StandardAnalyzer()); qp.setDefaultOperator(QueryParser.AND_OPERATOR); qp.setAutoGeneratePhraseQueries(true);
IKQueryExpressionParser 类中方法 BooleanQuery ,在近期的 lucene 中有了较大改动,不知道的话,能够 查阅个人上一篇文章lucene6.6 学习心得.
所以源码中对 IKQueryExpressionParser 类中关于 BooleanQuery 的方法都须要进行更改。
由于方法中代码过多 , 所以,我选取其中比较关键的几个地方,进行展现。
关键源码以下:
private Query toBooleanQuery(Element op) { BooleanQuery resultQuery = new BooleanQuery(); Query q2 = this.querys.pop(); Query q1 = this.querys.pop(); BooleanClause[] clauses = ((BooleanQuery) q1).getClauses(); resultQuery.add(c); return resultQuery; }
改动代码以下:
1.数组版本
private Query toBooleanQuery(Element op){ BooleanQuery.Builder builder = new BooleanQuery.Builder(); Query q2 = this.querys.pop(); Query q1 = this.querys.pop(); //由于,我看源码,并无发现会增删的地方 ,因而直接转成了数组 //迭代器版本的在下文 if(q1 instanceof BooleanQuery){ BooleanClause[] clauses =(BooleanClause[]) ((BooleanQuery)q1).clauses().toArray(); if(clauses.length > 0 && clauses[0].getOccur() == Occur.MUST){ for(BooleanClause c : clauses){ builder.add(c); } }else{ builder.add(q1,Occur.MUST); } return builder.build(); }
2.迭代器版本
private Query toBooleanQuery(Element op){ BooleanQuery.Builder builder = new BooleanQuery.Builder(); Query q2 = this.querys.pop(); Query q1 = this.querys.pop(); if(q1 instanceof BooleanQuery){ Iterator<BooleanClause> clauses = ((BooleanQuery) q1).iterator(); while (clauses.hasNext()) { BooleanClause clause = clauses.next(); if (clause.getOccur() == Occur.MUST) { builder.add(clause); } else { builder.add(q1,Occur.MUST); } } return builder.build(); }
打开包中的测试代码
1.IKAnalzyerDemo
运行结果以下图
2.LuceneIndexAndSearchDemo
运行结果以下图
源码与整合包 已经上传至个人 GitHub 上,有兴趣的能够去那里下载,不嫌弃的话,Star 一下 ,也是能够的哦~