您的位置:首页 > 其它

solr的安装以及配置中文分词器

2018-01-17 09:34 609 查看
(转载自http://blog.csdn.net/liaomin416100569/article/details/77301756)

一 。solr简介

    solr是以lucene为内核开发的企业级搜索应用  应用程序可以通过http请求方式来提交索引,查询索引,提供了比lucene更丰富的查询语言,是一个高性能,高可用环境全文搜索引擎

二 。solr安装配置

     1》下载solr安装包  

solr所有版本 (http://archive.apache.org/dist/lucene/solr/) 

           这里下载 solr-5.5.4

     2》安装 解压将solr-5.5.4\server\solr-webapp下的webapp 拷贝到tomcat\webapps目录下 改名为solr 启动tomcat

       直接访问 出现404  找到tomcat/logs/localhost.2017-08-17.log 日志  出现以下异常

[html] view
plain copy

java.lang.NoClassDefFoundError: Failed to initialize Apache Solr: Could not find necessary SLF4j logging jars.   

If using Jetty, the SLF4j logging jars need to go in the jetty lib/ext directory. For other containers,   

the corresponding directory should be used. For more information, see: http://wiki.apache.org/solr/SolrLogging  

    at org.apache.solr.servlet.CheckLoggingConfiguration.check(CheckLoggingConfiguration.java:27)  

    at org.apache.solr.servlet.BaseSolrFilter.<clinit>(BaseSolrFilter.java:30)  


      可用看到缺少SLF4j包 应该去 应该去 解压包 /server/lib/ext下找到并拷贝到 tomcat/solr/lib目录下  然后重启

    继续访问 出现以下错误 

[html] view
plain copy

java.lang.NoSuchMethodError: javax.servlet.ServletInputStream.isFinished()Z  

    org.apache.solr.servlet.SolrDispatchFilter.consumeInputFully(SolrDispatchFilter.java:284)  

    org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:274)  

    org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:208)  

    明显是Servlet版本不一致  tomcat6不支持solr5.54 加大tomcat版本 tomcat7也不支持 换成tomcat8  启动后访问 依然错误:

[html] view
plain copy

org.apache.solr.common.SolrException: Error processing the request. CoreContainer is either not initialized or shutting down.  

    org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:217)  

    org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:208)  

   是因为需要配置solrhome环境

   3》配置solrhome

     找到 tomcat\solr\WEB-INF\web.xml 编辑  找到以下这段(配置solrhome)  去掉注释 将第二个参数配置为本地任意一个目录即可 

[html] view
plain copy

<env-entry>  

   <env-entry-name>solr/home</env-entry-name>  

   <env-entry-value>D:\learn\solr-5.5.4\home</env-entry-value>  

   <env-entry-type>java.lang.String</env-entry-type>  

</env-entry>  

   找到solr解压包/server/solr目录拷贝所有文件到 以上web.xml指定的路径D:\learn\solr-5.5.4\home下 重启tomcat 访问

   http://localhost:8080/solor/index.html  或者 http://localhost:8080/solr/admin.html  

  


   4》配置core(core类似于数据库可以插入多个document(数据库表行)每个document拥有多个 field 数据库的列)

   solrhome下新建一个core目录  比如mycore

   拷贝 solr解压包下\server\solr\configsets\basic_configs到新建目录 mycore中

  进入solr管理网页 点击 core admin 添加该core

 


  点击Add core后 成功后 检查 mycore目录 发现多了 core.properties和data两个资源



 登陆solr管理网站发现 列表中多了mycore



 4》配置文件理解

    core/conf目录下的两个配置文件非常重要 

    managed-schema 主要用于配置 可以提交到该core的所有field定义,field的类型定义,唯一标识符等

    常用配置如下:

[html] view
plain copy

定义字段 _version_ 类型为long  indexed="true" 会进行分词索引  stored="true"表示存储到磁盘  

<field name="_version_" type="long" indexed="true" stored="true"/>  

定义字段 id required="true" 表示所有的document必须添加id字段 multiValued="false" 表示是否是多值字段  

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />   

定义动态字段 所以_i结尾的字段都可以写入到当前的core  

<dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>  

定义唯一标识符的字段  

<uniqueKey>id</uniqueKey>  

定义字段类型的别名  

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

  solrconfig.xml 主要用于配置solor的主要配置信息
比如lucene版本 缓存 数据目录 请求路径映射 等 

[html] view
plain copy

表示lucene版本  

<luceneMatchVersion>5.5.4</luceneMatchVersion>  

表示数据目录 默认是data目录  

<dataDir>${solr.data.dir:}</dataDir>   

自动提交配置  

<autoCommit>   

       当超过15000ms后自动提交所有数据  

       <maxTime>${solr.autoCommit.maxTime:15000}</maxTime>   

       是否马上就可以查询到  

       <openSearcher>false</openSearcher>   

</autoCommit>  

表示当路径为 /select时查询所有的数据  

<requestHandler name="/select" class="solr.SearchHandler">  

    <!-- default values for query parameters can be specified, these  

         will be overridden by parameters in the request  

      -->  

     <lst name="defaults">  

       <str name="echoParams">explicit</str>  

       <int name="rows">10</int>  

     </lst>  

</requestHandler>  

 尝试在界面上添加数据和查询数据

 添加数据

 




 查询结果

 


查询的参数列表

  q表示查询的条件  字段名:值的格式

  fq表示filter query 过滤条件 和q是and的关系支持各种逻辑运算符 (参考https://cwiki.apache.org/confluence/display/solr/The+Standard+Query+Parser)

  sort表示排序 的字段  字段名 asc|desc 

  start 表示从第几行开始  rows表示查询的总行数

  fl表示查询显示的列 比如只需要查询 name_s,sex_i 这两列 使用,隔开

  df表示默认的查询字段 一般不设置

  Raw Query Parameters表示原始查询字段 可以使用 start=0&rows=10这种url的方式传入参数

  wt(write type)表示写入的格式 可以使用json和xml

  shards 多核同时搜索 solrhome拷贝mycore为mycore1  管理平台添加core   设置参数为 路径,路径来设置需要搜索的核

[html] view
plain copy

String shards = "localhost:8080/solr/mycore,localhost:8080/solr/mycore1";   

query.set("shards", shards);  

  其他参考(https://cwiki.apache.org/confluence/display/solr/Common+Query+Parameters)

 5》配置中文分词器

   默认solr 没有使用中文分词器  所有搜索的词 都是整个句子就是一个词 搜索时 将单词全部写入才能搜索或者使用* 需要配置中文分词器

目前比较好用的分词器 是IK  2012年停更 只支持到 Lucene4.7 所有 solr5.5 需要lucene5支持  需要修改部分源码来支持solr5.5

 找到 IKAnalyzer类   需要重写  protected TokenStreamComponents createComponents(String fieldName) 方法

 找到 IKTokenizer类 需要重写构造方法  public IKTokenizer(Reader in, boolean useSmart) 为  public IKTokenizer(boolean useSmart) {

 在任意项目中 使用maven 引用lucene5 和ik view
plai

<dependencies>
<dependency>
<groupId>com.janeluo</groupId>
<artifactId>ikanalyzer</artifactId>
<version>2012_u6</version>
<!-- 解决jar包冲突问题,将lucene4.7的jar全部排出,因为版本会冲突,ik只支持Lucene4.7 -->
<exclusions>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queries</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-sandbox</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>
<!-- 引入Lucene5.5.4 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>5.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queries</artifactId>
<version>5.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-sandbox</artifactId>
<version>5.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>5.5.4</version>
</dependency>
</dependencies>

 cop在项目中
添加完整的包名和类名 和 ik中一致 拷贝源代码



代码修改对应的方法即可

IKAnalyzer

[html] view
plain copy

/**  

  

 *  

 */  

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

[html] view
plain copy

/**  

 *   

 */  

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);  

  }  

}  

将编译好的class文件(如此路径:E:\eclipsWorkspace\IK\target\classes\org\wltea\analyzer\lucene)替换原始jar包即可

将solrhome下 配置文件managed-schema 添加一个字段类型 使用ik分词器

[html] view
plain copy

<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该字段类型 比如

[html] view
plain copy

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

重启 或者 cloud环境下重新生成collection 插入数据即可实现中文分词  通过某些中文关键字搜索
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: