在中文分詞器中, 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 一下 ,也是能夠的哦~