Solr6.5配置中文分词器

 

Solr做为搜索应用服务器,咱们在使用过程当中,不可避免的要使用中文搜索。如下介绍solr自带的中文分词器和第三方分词器IKAnalyzer。java

 注:下面操做在Linux下执行,所添加的配置在windon下依然有效。web

运行环境面试

    •   Solr:6.5.1
    •   系统 : Linux

 

如下是设置 solr中文分词器的方法。apache

注:开始以前,假定你已经成功登陆solr的界面,并建立了core。tomcat

一:使用solr自带 中文分词器服务器

一、进入解压好的solr文件夹根目录下执行如下命令app

1 cp ./contrib/analysis-extras/lucene-libs/lucene-analyzers-smartcn-6.5.1.jar /opt/tomcat-solr/webapps/solr/WEB-INF/lib/ 

复制lucene-analyzers-smartcn-6.5.1.jar该文件到 Tomcat下的 solr web应用中的lib目录下,不清楚的能够看 执行命令的地址。复制的文件就是 solr自带的中文分词器。webapp

注:若是没有解压的目录,那么在solrhome的目录下也存在contrib这个文件夹,若是你已经成功登陆过solr界面的话。ide

 

二、进入core目录下的conf文件夹,测试

打开 managed-schema文件,跳至文件最后,在最后添加新的字段类型以下

1 <!--solr cnAnalyzer-->
2   <fieldType name="solr_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
3       <analyzer type="index">
4         <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
5       </analyzer>
6       <analyzer type="query">
7         <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
8       </analyzer>
9   </fieldType>
 

  fieldType: 字段类型属性

name: 字段类型名称(能够理解为Java的 数据类型名称。例如: int、double、String等Java中的数据类型名称)

class: 数据类型(默认文本数据便可,还有其余的例如:字符串、浮点、整形等)
看下面的配置文件中 其余字段类型,应该很容易理解了:

1  <!-- 字符串 -->
2    <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
3  <!-- 布尔类型 -->
4    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
5  <!-- 整形 -->
6     <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
7  <!-- 浮点 -->
8     <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
  positionIncrementGap:一个doc中的属性有多个值时候,设置每一个属性之间的增量值和multiValued属性配合使用(避免错误匹配)。
  type: 分词生效的范围,两个参数分别是 index和query,表示 建立索引和搜索时候都生效。不写默认状况下二者均生效。
 

 三、添加完毕以后,保存退出并从新启动 Tomcat服务器,继续访问solr。在建立的core中 Analyzer测试中文分词结果以下。

 测试以后,能够看到 短语确实被分割了,可是有些中止词没有被去掉(的、是),也没有去除符号(,),能够在属性上添加 words添加停词字典。那么咱们下面试试第三方的分词器.

 

二:solr 第三方中文分词器 IKAnalyzer

  在使用IKAnalyzer分词器以前,先说明因为做者在12年以后没有更新,致使旧版本的分词器和新版本的solr没法匹配。所以在源码的基础上作些改动,以兼容新版的solr。

一、首先修改分词器:

IK的分词器 IKTokenizer类实现了抽象类Tokenizer。在IKTokenizer的构造方法中调用了父类Tokenizer的构造方法,代码以下

1   public IKTokenizer(Reader in, boolean useSmart) { 2       super(in); 3       offsetAtt = addAttribute(OffsetAttribute.class); 4       termAtt = addAttribute(CharTermAttribute.class); 5       typeAtt = addAttribute(TypeAttribute.class); 6       _IKImplement = new IKSegmenter(input, useSmart); 7   }

Tokenizer构造器:

1 protected Tokenizer(AttributeFactory factory) {
2     super(factory);
3   } 

能够看到上面的代码中,构造器调用了父类的构造器,出现不兼容的缘由是由于如今的抽象类Tokenizer的构造方法中接受的是 AttributeFactory这个类型,而IKTokenizer传递的Reader不匹配。因此在此基础上作了以下修改

 1     //分析器调用
 2     public IKTokenizer(Reader in, boolean useSmart) {  3         offsetAtt = addAttribute(OffsetAttribute.class);  4         termAtt = addAttribute(CharTermAttribute.class);  5         typeAtt = addAttribute(TypeAttribute.class);  6         _IKImplement = new IKSegmenter(input, useSmart);  7  }  8     
 9     //分词器工厂调用
10     public IKTokenizer(AttributeFactory factory, boolean useSmart) { 11         super(factory); 12         offsetAtt = addAttribute(OffsetAttribute.class); 13         termAtt = addAttribute(CharTermAttribute.class); 14         typeAtt = addAttribute(TypeAttribute.class); 15         _IKImplement = new IKSegmenter(input, useSmart); 16     }

在第一个代码中删除了调用父类构造器的过程,主要用于分析器调用,而后第二个是由于 在设置配置文件managed-schema中设置分析器和构造器结合使用的时候须要用到工厂类,所以在此处也建立了一个新的构造方法,接收一个AttributeFactory类型的参数 ,下面会看到他的用处。

 

二、分析器 IKAnalyzer。

IK分析器中IKAnalyzer重写父抽象类Analyzer中的createComponents方法,原代码以下

1   /**
2  * 重载Analyzer接口,构造分词组件 3    */
4  @Override 5   protected TokenStreamComponents createComponents(String fieldName, final Reader in) { 6       Tokenizer _IKTokenizer = new IKTokenizer(in, this.useSmart()); 7     return new TokenStreamComponents(_IKTokenizer); 8   }

因为如今的Analyzer的抽象方法createComponents,只须要一个 fieldName参数,并不须要Reader,所以直接删除Reader便可。同时由于分词器中也不须要Reader对象,在原来的分词器IKAnalyzer是接收Reader对象后又传递给了父类的构造器,可是在新版的solr中不须要了,并且分词器IKAnalyzer中也没有使用该对象。

1  @Override 2     protected TokenStreamComponents createComponents(String fieldName) { 3         IKTokenizer it = new IKTokenizer(useSmart); 4         return new Analyzer.TokenStreamComponents(it); 5     }

其实并没更改什么,去掉了Reader,而后建立分词器实例返回。若是这时候在managed-schema配置文件中设置分析器已经可使用了 以下:

1 <fieldType name="IK_cnAnalyzer" class="solr.TextField">
2   <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
3 </fieldType>

  直接指定修改后的IK分词器给分析器。在单独给分析器指定分词器时候,不要在 fieldType(字段类型) 加上positionIncrementGap 参数,不然会报错:

  java.lang.RuntimeException: Can't set positionIncrementGap on custom analyzer class org.wltea.analyzer.lucene.IKAnalyzer

  直接使用solr中文分析器时候,一样没法指定 fieldType 的 属性positionIncrementGap,那么应该 solr在直接设定 分析器的时候是没法指定该属性的。

 注:analyzer(分析器)上还能够设置 type属性,告诉solr在何时会生效。分别是index和query,在建立索引时候生效,在查询时候生效。默认不写同时生效.

   class:直接指定的分析器(Analyzer)不能是分词的工厂类(Factory)或者分词器(Tokenizer)

上面的修改已经可使用分析器了,可是若是和分词器和过滤器配合使用,那么必须建立一个能够生产分词器的工厂类。该工厂类实org.apache.lucene.analysis.util.TokenizerFactory抽象类.并且必须实现create方法。

同时还要在构造器中调用父接口的构造器,并传递一个Map类型的参数。

 

三、IKTokenizerFactory工厂类

 1 package org.wltea.analyzer.lucene;  2 
 3 import java.util.Map;  4 
 5 import org.apache.lucene.analysis.Tokenizer;  6 import org.apache.lucene.analysis.util.TokenizerFactory;  7 import org.apache.lucene.util.AttributeFactory;  8 
 9 /**
10  * IK分词工厂类。 用于配置文件中 分析器添加分词器(必须工厂类)。 11  */
12 public final class IKTokenizerFactory extends TokenizerFactory { 13 
14     private boolean useSmart; 15 
16     // 从页面传递的值中。设置 useSmart 的值
17     public IKTokenizerFactory(Map<String, String> args) { 18         super(args); 19         /*
20  * 判断Map容器中是否存在useSmart的能够,若是有获取该key对应的value。 21  * 若是没有,则设置默认值,也就是第三个参数 false 22          */
23         useSmart = this.getBoolean(args, "useSmart", false); 24         if (!args.isEmpty()) { 25             throw new IllegalArgumentException("Unknown parameters: " + args); 26  } 27  } 28 
29  @Override 30     public Tokenizer create(AttributeFactory factory) { 31         return new IKTokenizer(factory, useSmart); 32  } 33 }

  能够看到该分词器实现父类的create方法时候接受了一个AttributeFactory, 是否是很熟悉,在上面修改的IKTokenizer中新增的构造器内接受该类型的参数,并调用父类的构造器,又将参数传递给了父类。

  所以IKTokenizer中的第二个构造器就是用于该工厂调用并传递参数,而后建立实例返回。

  至于另一个问题,构造器必须调用父类的构造器,而后建立Map类型的参数,传递给父类构造器,是由于父类TokenizerFactory只有一个带参数的构造器,没有默认构造器。子类IKTokenizerFactory在初始化过程当中,必须调用父类的构造器。即便传递null值给父类。

  而Map容器的做用是:在配置文件managed-schema中,设置分词器的时候,能够传递参数。用于设置分词器中的参数,例如上面的 useSmart,就是用于IK分词器是否开启智能分词的关。

  至此修改所有完毕,最后只须要将修改后的编译文件放入 IK的jar包内便可。注意包路径为

org.wltea.analyzer.lucene

  若是以为修改麻烦,能够直接下载修改后的文件  下载地址:点我下载 压缩包内包含了 修改后的文件,和 IK的源码等。

  

  四、IK在Linux上的设置方式

  先将IK的jar文件和配置文件上传到Linux系统中

复制 IK jar包到 solr/WEB-INF/lib 目录下

1 cp IKAnalyzer2012FF_u1-6.51.jar /opt/tomcat-solr/webapps/solr/WEB-INF/lib/

复制配置文件到 solr/WEB-INF/classes目录下

1 cp ext.dic IKAnalyzer.cfg.xml stopword.dic /opt/tomcat-solr/webapps/solr/WEB-INF/classes/

  进入solrhome中打开managed-schema文件,添加IKAnalyzer

  个人路径配置路径:/opt/tomcat-solr/solrhome/home/mycore/conf  请根具我的路径修改配置文件

  

  五、在上问添加solr中文分词器后面重现加入如下代码

 1 <!-- IKAnalyzer -->
 2 <fieldType name="IK_cnAnalyzer" class="solr.TextField" positionIncrementGap="100">
 3      <analyzer type="index">
 4       <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
 5     </analyzer>
 6      <analyzer type="query">
 7          <tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false"/>
 8       </analyzer>
 9  </fieldType>
10  
11   <!-- IKAnalyzer Field-->
12   <field name="IK_content" type="IK_cnAnalyzer" indexed="true" stored="true"/>

注:若是在操做以前,经过solr界面的 AddField 方式添加了新的字段,那么 配置文件 中的数据会被solr所有从新更改,字段类型出如今第一行。全部请根据状况修改配置文件

 

  在analyzer(分析器)中设置了 index和query说明建立索引和查询的时候都使用分词,所以若是有特殊要求,能够指定索引和查询时候设置不一样的分词器。

  useSmart为工厂对象的构造方法接受的参数,就是上面说到的分词工厂类中的 Map接受该参数。设置是否使用智能分词.默认为false,使用细粒度分词

注:此处的 class只能是工厂对象,并由工厂对象负责建立分词器实例。工厂对象须要继承org.apache.lucene.analysis.util.TokenizerFactory这个抽象类,并实现其中的create方法,实现的工厂对象必须用final修饰。

   添加分词结果后的managed-schema文件以下:

 

六、添加完保存以后,从新访问 solr,而后在 core的 Analyzer中测试结果以下

 

 由于新增的字段 IK_content,指定的字段类型是IK_cnAnalyzer,该类型使用的是IK中文分词器,因此使用指定字段或者字段类型,分词结果是同样的。

 

七、设置ik的扩展词库,

在/opt/tomcat-solr/webapps/solr/WEB-INF/classes 目录下的能够设置 ik的扩展字典

 

如今打开配置文件 IKAnalyzer.cfg.xml,

而后在打开扩展字典 配置文件 ext.dic 添加 全文搜索、服务器。而后重启 Tomcat。

 

八、重启Tomcat服务器以后,继续分词查看结果以下

 

很显然扩展字典生效了,出现了新增的全文搜索、服务器两个词组,所以若有须要能够在扩展字典中添加词组。至于后面重复出现词组(分词后的),是由于IK分词子默认开启了细粒度的分词,若是须要开启智能分词能够将配置文件中的 useSmart 设置为true便可。 下面是开启智能分词后的结果:

  能够根据需求是否开启智能分词,至此solr的中文分词到此结束。

  总结:

    设置solr的分词只须要将分词器的jar包放入solr的依赖文件内,而后在核心core中的managed-schema设置须要的分词便可。

 文章有不少不足的地方,欢迎你们指正!

相关文章
相关标签/搜索