企业级搜索solr应用

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

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

 继续访问 出现以下错误 


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


3》配置solrhome

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

html代码

<env-entry>  
   <env-entry-name>solr/home</env-entry-name>  
   <env-entry-value>D:\solrhome</env-entry-value>  
   <env-entry-type>java.lang.String</env-entry-type>  
</env-entry>

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

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


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

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

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

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

>Name:mycore,instanceDir:mycore,其它不变

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

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


4》配置文件理解

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

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

常用配置如下:

html代码

定义字段 _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代码

表示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>  

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

 添加数据

>打开Documents下  添加更新 如: {"id":"1","foodname_ik":"白切鸡"}

>打开query 查询  如:  foodname_ik:青椒

如图所示:




查询的参数列表

  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   设置参数为 路径,路径来设置需要搜索的核

代码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 夹包

<dependencies>

<dependency>

  <groupId>com.janeluo</groupId>

  <artifactId>ikanalyzer</artifactId>

  <version>2012_u6</version>

</dependency>

</dependencies>

修改版本将lucene4.7替换成 lucene5.5.4

<!-- 1 deploy(安装jar包到私服) install(安装jar到本地仓库) package(打包) 区别 2 怎么解决mavenjar冲突问题

:就是下面这个去掉版本,引用合适版本 -->

<dependencies>

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

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

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

 >例如:IK项目 src/main/java/创建包

>Org.wltea.analyzer.lucene包下创建类

IKAnalyzer.java IKTokenizer.java


代码修改对应的方法即可

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

>然后如:E:\Maven\MAVEN\apache-maven-3.0.4_localtest\resp\com\janeluo\ikanalyzer\2012_u6

 目录下拷贝ikanalyzer-2012_u6.jar 这个夹包到桌面然后再用WinRAR文件打开--------->进入

org.wltea.analyzer.lucene目录下:删除这两个文件 IKAnalyzer.classIKTokenizer.clas

-----> eclipse将改好的项目里的maven夹包下的org.wltea.analyzer.lucene的两个文件 IKAnalyzer.classIKTokenizer.class拷到上面的WinRAR文件打开的org.wltea.analyzer.lucene目录下:粘贴替换

 

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

html

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

然后将对应需要进行中文分词的字段使用 text_ik该字段类型 比如

html

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值