1. 程式人生 > >Solr學習總結 IK 配置中文分詞器

Solr學習總結 IK 配置中文分詞器

  預設solr沒有使用中文分詞器 所有搜尋的詞都是整個句子是一個詞 需要配置中文分詞器目前比較好用的是IK 但2012就停更了 只支援到Lucene4.7所有solr5.5需要Lucene5支援需要修改部分原始碼來支援solr5.5找到IKAnalyze類 

<dependency>
	    <groupId>com.janeluo</groupId>
	    <artifactId>ikanalyzer</artifactId>
	    <version>2012_u6</version>
	</dependency>

因為IK分詞器底層本來就是用lucene一些技術來實現的所以會給一些相關聯的包給下載下來但Lucene4.7.2跟solr5版本差異非常大所以需要改寫其中的一些類然後再重新打包

 

首先 先找到 IKAnalyzer這個類因為需要修改它的原始碼所以要去模仿它(包名類名內容需一致) 由於java遵守就近原則 它就不會去載入jar包裡的內容了會以當前類為主  本身的Ik是支援4.7.2的所以當前這個類也是能編譯通過的

 

程式碼修改對應的方法即可

IKAnalyzer

/**
 
 *
 */
package org.wltea.analyzer.lucene;
 
import java.io.Reader;
 
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
 
/**
 */
public final class IKAnalyzer extends Analyzer {
 
  private boolean useSmart;
 
  public boolean useSmart() {
    return useSmart;
  }
 
  public void setUseSmart(boolean useSmart) {
    this.useSmart = useSmart;
  }
 
  /**
 
   */
  public IKAnalyzer() {
    this(false);
  }
 
  /**
   */
  public IKAnalyzer(boolean useSmart) {
    super();
    this.useSmart = useSmart;
  }
 
  /**這裡就去掉了 Reader的一個引數
   */
  @Override
  protected TokenStreamComponents createComponents(String fieldName) {
    Tokenizer _IKTokenizer = new IKTokenizer(this.useSmart());
    return new TokenStreamComponents(_IKTokenizer);
  }
 
}

IKTokenizer

/**
 * 
 */
package org.wltea.analyzer.lucene;
 
import java.io.IOException;
import java.io.Reader;
 
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
 
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
 
 
public final class IKTokenizer extends Tokenizer {
 
 
  private IKSegmenter _IKImplement;
 
 
  private final CharTermAttribute termAtt;
 
  private final OffsetAttribute offsetAtt;
 
  private final TypeAttribute typeAtt;
 
  private int endPosition;
 
  //去掉了其中Reader的第一個構造引數
  public IKTokenizer(boolean useSmart) {
    super();//去掉super中的構造引數
    offsetAtt = addAttribute(OffsetAttribute.class);
    termAtt = addAttribute(CharTermAttribute.class);
    typeAtt = addAttribute(TypeAttribute.class);
    _IKImplement = new IKSegmenter(input, useSmart);
  }
 
 
  @Override
  public boolean incrementToken() throws IOException {
 
    clearAttributes();
    Lexeme nextLexeme = _IKImplement.next();
    if (nextLexeme != null) {
 
      termAtt.append(nextLexeme.getLexemeText());
   
      termAtt.setLength(nextLexeme.getLength());
      
      offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
   
      endPosition = nextLexeme.getEndPosition();
  
      typeAtt.setType(nextLexeme.getLexemeTypeString());
 
      return true;
    }
 
    return false;
  }
 
  /*
   * (non-Javadoc)
   * @see org.apache.lucene.analysis.Tokenizer#reset(java.io.Reader)
   */
  @Override
  public void reset() throws IOException {
    super.reset();
    _IKImplement.reset(input);
  }
 
  @Override
  public final void end() {
    // set final offset
    int finalOffset = correctOffset(this.endPosition);
    offsetAtt.setOffset(finalOffset, finalOffset);
  }
}

 

強制性的把依賴 換成自己需要的版本

剔除 

<dependencies>
 	<!-- https://mvnrepository.com/artifact/com.janeluo/ikanalyzer -->
	<dependency>
	    <groupId>com.janeluo</groupId>
	    <artifactId>ikanalyzer</artifactId>
	    <version>2012_u6</version>
	    <!-- 剔除 -->
	    <exclusions>
	    	<exclusion>
		    <groupId>org.apache.lucene</groupId>
		    <artifactId>lucene-core</artifactId>
		</exclusion>
		<exclusion>  
			 <groupId>org.apache.lucene</groupId>
		    <artifactId>lucene-queryparser</artifactId>
	    </exclusion>
	   	<exclusion>  
			 <groupId>org.apache.lucene</groupId>
		    <artifactId>lucene-analyzers-common</artifactId>
		</exclusion>
	    </exclusions>
	</dependency>
    <!-- 替換成自己需要的版本 -->
	<dependency>
		<groupId>org.apache.lucene</groupId>
		<artifactId>lucene-core</artifactId>
		<version>5.5.5</version>
	</dependency>
	<dependency>
		<groupId>org.apache.lucene</groupId>
		<artifactId>lucene-queryparser</artifactId>
		<version>5.5.5</version>
	</dependency>
	<dependency>
		<groupId>org.apache.lucene</groupId>
		<artifactId>lucene-analyzers-common</artifactId>
		<version>5.5.5</version>
	</dependency>
  </dependencies>

這時候4.7.2就替換成5.5.5了

在資料夾中找到 ikanalyzer-2012_u6.jar

雖然修改了java專案但包裡面的內容並沒有修改所以需要把編譯好的class檔案替換原始jar  替換完成後就支援5.5版本了

將solrhome下 配置檔案managed-schema 新增一個欄位型別 使用ik分詞器

<fieldType name="text_ik" class="solr.TextField" >
      <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>   
      <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/> 
    </fieldType>

不能修改 StrField 不支援自定義分詞器

<fieldType name="string" class="solr.StrField" sortMissingLast="true" >
</fieldType>

然後將對應需要進行中文分詞的欄位使用 text_ik該欄位型別 比如

<dynamicField name="*_s"  type="text_ik"  indexed="true"  stored="true" />

重啟 或者 cloud環境下重新生成collection 插入資料即可實現中文分詞  通過某些中文關鍵字搜尋