Solr全文搜索引擎
概述
在一些大型门户网站、电子商务网站等都需要站内搜索功能,使用传统的
数据库查询方式实现搜索无法满足一些高级的搜索需求,比如:搜索速度要快
、搜索结果按相关度排序、搜索内容格式不固定等,这里就需要使用全文检索
技术实现搜索功能。
1.1 单独使用 Lucene 实现
单独使用Lucene实现站内搜索需要开发的工作量较大,主要表现在:索
引维护、索引性能优化、搜索性能优化等,因此不建议采用。
1.2 使用 Google 或 Baidu 接口
通过第三方搜索引擎提供的接口实现站内搜索,这样和第三方引擎系统
依赖紧密,不方便扩展,不建议采用。
1.3 使用 Solr 实现
基于Solr实现站内搜索扩展性较好并且可以减少程序员的工作量,因为S
olr提供了较为完备的搜索引擎解决方案,因此在门户、论坛等系统中常用此方
案。
什么是Solr
什么是solr?
Solr是一个Apache开源项目, 它基于Java语言进行开发, 并作为Lucene的全文搜索引擎的基础而存在.
solr的优点:
Solr可以独立运行,Solr根据xml文档添加、删除、更新索引 。Solr
搜索只需要发送 HTTP GET 请求,然后对 Solr返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

Solr 与 Lucene 的区别
Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文
检索引擎,Lucene提供了完整的查询引擎和索引引擎,目的是为软件开发人员
提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或
者以Lucene为基础构建全文检索引擎。
Solr的目标是打造一款企业级的搜索引擎系统,它是一个搜索引擎服务,可以
独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。
Solr的安装配置
下载
从Solr官方网站(http://lucene.apache.org/solr/)下载Solr4.10.3,
根据Solr的运行环境,Linux下需要下载lucene-4.10.3.tgz,
Linux-Solr下载地址:http://archive.apache.org/dist/lucene/solr/
windows下需要下载lucene-4.10.3.zip。
Solr使用指南可参考:https://wiki.apache.org/solr/FrontPage。
- 下载lucene-4.10.3.zip并解压:

binary scripts for solr execution
contrib: additional software and plugins contributed to enhance solr’s functionality
dist: directory contains Java web applications (war) and libraries (jar) generated during the build process
docs: API documentation for solr
example: example directories showcasing different aspects of solr deployment:
example/solr: A core directory with default configuration information for Solr
example/multicore: A directory containing multiple cores configured for parallel processing in Solr
example/webapps: A directory containing a single solr.war application, which serves as the runtime instance
licenses: A directory containing a single solr.war application, which serves as the runtime instance
solr的运行环境
solr需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jetty(java写的Servlet容器),本教程使用Tocmat作为Servlet容器,环境如下:
Solr:Solr4.10.3
Jdk:jdk1.7.0_72
Tomcat:apache-tomcat-7.0.53
Solr 与 Tomcat 整合配置
Solr下载地址:http://archive.apache.org/dist/lucene/solr/
安装Solr与Tomcat集成:Linux-CentOS6以上、Tomcat7.0以上、Solr4.10.3
安装步骤:
解压Solr:tar -zxvf solr-4.10.3.tgz.tar
进入目录:cd solr-4.10.3/example/webapps/
拷贝其文件夹下的war文件到tomcat的webapps文件夹中:cp solr.war /usr/local/solr-tomcat/webapps/
解压Solr:mkdir solr && unzip solr.war -d solr && rm rf solr.war
修改解压好的solr文件夹,修改其文件,vim solr/WEB-INF/web.xml 查找到nv-entry内容,解开注释文本,并修改solr/home的地址,/usr/solr-4.10.3/example/solr,保存并退出即可。
拷贝相关jar包到tomcat下:cd /usr/solr-4.10.3/example/lib/ext && cp * /usr/solr-tomcat/lib/
启动tomcat端口即可:/usr/solr-tomcat/bin/startup.sh
查看日志:tail -n 500 /usr/solr-tomcat/logs/catalina.out
通过浏览器访问:http://localhost:8080/solr/,查看solr主页即可。
Dashboard :
仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等
信息。
Logging :
Solr运行日志信息
Cloud :
Cloud即SolrCloud,即Solr云(集群),当使用Solr
Cloud模式运行时会显示此菜单,如下图是Solr Cloud的管理界面:
Solr 全文检索服务 :
Core Admin :
Solr Core的管理界面。Solr Core
是Solr的一个独立运行实例单位,它可以对外提供索引和搜索服务,一个Solr工
程可以运行多个SolrCore(Solr实例),一个Core对应一个索引目录。
java properties
Solr在JVM
运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。
Tread Dump
显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。
Core selector
选择一个SolrCore进行详细操作,如下:

Analysis

通过此界面可以测试索引分析器和搜索分析器的执行情况。
dataimport
可以定义数据导入处理器,从关系数据库将数据导入 到Solr索引库中。
Document
通过此菜单可以创建索引、更新索引、删除索引等操作,界面如下:

/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内
容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。
query

通过/select执行搜索索引,必须指定“q”查询条件方可搜索。
Solr 索引
scheam.xml
schema.xml,在SolrCore的conf目录下,它是Solr数据表配置文件,它定义
了加入索引的数据的数据类型的。主要包括FieldTypes、Fields和其他的一些缺省设置。

FieldType
下边“text_general”是Solr默认提供的FieldType,通过它说明FieldType定义的 内容:

FieldType子结点包括:name,class,positionIncrementGap等一些参数:
name:是这个FieldType的名称
class:是Solr提供的包solr.TextField,solr.TextField
允许用户通过分析器来定制索引和查询,分析器包括一个分词器(tokenizer)
和多个过滤器(filter)
positionIncrementGap:可选属性,定义在同一个文档中此类型数据的空白
间隔,避免短语匹配错误,此值相当于Lucene的短语查询设置slop值,根据经
验设置为100。
在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进
行查询的时候要使用的分析器analyzer,包括分词和过滤索引分析器中:使用solr.StandardTokenizerFactory标准分词器,solr.StopFilte
rFactory停用词过滤器,solr.LowerCaseFilterFactory小写过滤器。
搜索分析器中:使用solr.StandardTokenizerFactory标准分词器,solr.StopFilte
rFactory停用词过滤器,这里还用到了solr.SynonymFilterFactory同义词过滤器。
Field
在fields结点内定义具体的Field,filed定义包括name,type(为之前定义过的
各种FieldType),indexed(是否被索引),stored(是否被储存),multiValued(
是否存储多个值)等属性。
如下:
<field name="name" type="text_general" indexed="true" stored="true"/>
<field name="features" type="text_general" indexed="true" stored="true"
multiValued="true"/>
multiValued:该Field如果要存储多个值时设置为true,solr允许一个Field存
储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和
小图),通过使用solr查询要看出返回给客户端是数组:

uniqueKey
Solr中默认定义唯一主键key为id域,如下:
<uniqueKey>id</uniqueKey>
Solr在删除、更新索引时使用id域进行判断,也可以自定义唯一主键。
copyField
copyField复制域,可以将多个Field复制到一个Field中,以便进行统一的检
索:
比如,输入关键字搜索title标题内容content,
定义title、content、text的域:

根据关键字只搜索text域的内容就相当于搜索title和content,将title和content
复制到text中,如下:

配置IK 域类型, 修改schema.xml
修改Solr的schema.xml文件,添加FieldType:
<!-- IKAnalyzer-->
<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>
根据需求配置自定义域
<!--IKAnalyzer Field-->
<field name="product_name" type="text_ik" indexed="true" stored="true" />
安装中文分词器Analyzer
IKAnalyzer 部署
拷贝IKAnalyzer的文件到Tomcat下Solr目录 中
将IKAnalyzer2012FF_u1.jar拷贝到 Tomcat的webapps/solr/WEB-INF/lib 下。
在Tomcat的webapps/solr/WEB-INF/下创建classes目录
将IKAnalyzer.cfg.xml、ext_stopword.dic mydict.dic copy到 Tomcat的webapps/solr/WEB-INF/classes
注意:ext_stopword.dic 和mydict.dic必须保存成无BOM的utf-8类型。
修改schema.xml 文件
FieldType
首先需要在types结点内定义一个FieldType子结点,包括name,class,等参数,name就是这个FieldType的名称,class指向org.apache.solr.analysis包里面对应的class名称,用来定义这个类型的行为。在FieldType定义的时候最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤修改Solr的schema.xml文件,添加FieldType:
<!-- IKAnalyzer-->
<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>
Field
FieldType定义好后就可以在fields结点内定义具体的field,filed定义包括name,type(即FieldType),indexed(是否被索引),stored(是否被储存),multiValued(是否有多个值)等
<!--IKAnalyzer Field-->
<field name="title_ik" type="text_ik" indexed="true" stored="true" />
<field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/>
测试

设置业务系统 Field
如果不使用Solr提供的Field可以针对具体的业务需要自定义一套Field,如下
是商品信息Field:
<!--product-->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
<field name="product_price" type="float" indexed="true" stored="true"/>
<field name="product_description" type="text_ik" indexed="true"
stored="false" />
<field name="product_picture" type="string" indexed="false" stored="true" />
<field name="product_catalog_name" type="string" indexed="true"
stored="true" />
<field name="product_keywords" type="text_ik" indexed="true" stored="false"
multiValued="true"/>
<copyField source="product_name" dest="product_keywords"/>
<copyField source="product_description" dest="product_keywords"/>
索引维护
使用/update进行索引维护,进入Solr管理界面SolrCore下的Document下:

SolrJ 完成索引维护
什么是SolrJ
solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常
在嵌入在业务系统中,通过SolrJ的API接口操作Solr服务,如下图:
创建索引
使用SolrJ创建索引,通过调用SolrJ提供的API请求Solr服务,Document通过
SolrInputDocument进行构建。
/** *说明:根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不
到id域则会执行添加操作,如果找到则更新。
*/
// 创建索引
public void testCreateIndex() throws SolrServerException,
IOException {
SolrServer solrServer = new HttpSolrServer(urlString);
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "c0001");
document.addField("product_name","solr全文检索");//商品名称
document.addField("product_price",86.5f);//商品价格
document.addField("product_picture","382782828.jpg");//商品图片
document.addField("product_description","这是一本关于solr的书籍!");//商品描述
document.addField("product_catalog_name","javabook");//商品分类
UpdateResponse response =solrServer.add(document);
// 提交
solrServer.commit();
}
删除索引
上边介绍的删除方法,使用SolrJ也可以完成,代码如下:
// 删除索引
/** *说明:deleteById(String id)根据id删除索引,此方法为重载方法,也可以传个多个id批量删除,也可以调用deleteByQuery() 根据查询条件删除
*/
@Test
public void testDeleteIndex() throws SolrServerException,IOException {
SolrServer solrServer = new HttpSolrServer(urlString);
//根据id删除
UpdateResponse response = solrServer.deleteById("c0001");
//根据多个id删除
// solrServer.deleteById(ids);
//自动查询条件删除
solrServer.deleteByQuery("product_keywords:教程");
// 提交
solrServer.commit();
}
SolrJ完成搜索


组合查询




分页,高亮




