Solr介绍
Solr是什么
Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务。
solr可以实现全文检索功能(索引、搜索),solr是可以独立运行在tomcat等web容器中。
Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
Solr主要对外提供索引和搜索服务。
Solr和lucene的区别
Lucene是一个全文检索的工具包(是一堆的jar 包,不能独立运行,由应用程序通过lucene的jar实现全文检索)。
Solr 是一个全文检索的服务,solr是运行在tomcat等web容器中,对外提供http 的索引和搜索服务。
Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。
Solr下载
Solr下载地址
inux下需要下载lucene-xxx.tgz,windows下需要下载lucene-xxx.zip。
Solr使用指南可参考
- Solr的目录文件:
bin:可执行的程序、脚本
contrib:扩展的包,用于索引和搜索
dist:存放Solr的工程(solr-4.10.3.war)和jar包,将工程部署到tomcat上即可运行
docs:使用说明文档
example:例子,存储了很多Solr开发使用的例子工程和目录结构等
example/solr:
该目录是一个包含了默认配置信息的Solr的Core目录。
example/multicore:
该目录包含了在Solr的multicore中设置的多个Core目录。
example/webapps:
该目录中包括一个solr.war,该war可作为solr的运行实例工程。
licenses:solr相关的一些许可信息
licenses:许可
Solr运行环境
Solr
Jdk
Tomcat
Solr安装配置
SolrCore的安装配置
- SolrHome和Solrcore
SolrHome是一个目录 ,是Solr运行的主目录 ,SolrHome目录中包括多个SolrCore目录,每个solrcore目录对应一个索引文件目录 。
SolrCore即solr实例对外提供索引和搜索服务。
SolrCore是一个逻辑的概念,将一个solr工程(部署在tomcat中)逻辑区别开以solrcore为单位的服务。 - 目录结构
SolrHome目录 结构(solr-xxx\solr-xxx\example\solr例子)
SolrCore目录 结构
- 创建SolrCore
*创建目录:
先创建SolrHome
F:\develop下创建solr目录 ,SolrHome目录放到F:\develop\solr下。
从solr-xxx\solr-xxx\example\solr中的所有文件包括bin复制到创建的solrHome中
SolrCore目录 :
*配置文件
在solrCore的conf 下有一个solrconfig.xml文件,此文件就是solrCore的配置文件:
加载jar包
以下配置是solrcore运行所加载的jar包:
solr.install.dir 表示SolrCore所在目录。
修改:
将solr下载包中的contrib、dist两个目录 拷贝到f:\develop\solr下
更改索引文件目录
每个SolrCore都有自己的索引文件目录 ,默认在SolrCore目录下的data中。
data数据目录下包括了index索引目录 和tlog日志文件目录。
如果不想使用默认的目录也可以通过solrConfig.xml更改索引目录 ,此处使用默认路径如下:
配置请求处理器
客户端请求Solr请求处理器,进行索引和搜索。
在solrconfig.xml中配置了很多的请求处理器
requestHandler请求处理器,定义了索引和搜索的访问方式。
通过/update维护索引,可以完成索引的添加、修改、删除操作。
提交xml、json数据完成索引维护
通过/select搜索索引。
设置搜索参数完成搜索,搜索参数也可以设置一些默认值,如下:
<requestHandler name="/select" class="solr.SearchHandler">
<!-- 设置默认的参数值,可以在请求地址中修改这些参数-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int><!--显示数量-->
<str name="wt">json</str><!--显示格式-->
<str name="df">text</str><!--默认搜索字段-->
</lst>
</requestHandler>
- Solr工程部署
将官方提供的Solr.war部署到tomcat下。
官方提供的solr的war包是dist\solr-xxx.war
第一步:部署solr.war
将dist\solr-xxx.war拷贝到Tomcat的webapp目录下改名为solr.war
找到bin/startup.bat,启动tomcat后,solr.war自动解压,将原来的solr.war删除
生成solr工程目录:
第二步:拷贝扩展包到solr工程
拷贝example\lib\ext 目录下所有jar包拷贝到Tomcat的webapp\solr\WEB-INF\lib目录下
第三步:设置solrHome
修改Tomcat目录 下webapp\solr\WEB-INF\web.xml文件,如下所示:
设置Solr home
第四步:拷贝log4j.properties文件
在 Tomcat下webapps\solr\WEB-INF目录中创建文件 classes文件夹,
复制Solr目录下example\resources\log4j.properties至Tomcat下webapps\solr\WEB-INF\classes目录
- 启动tomcat
solr的主界面
- solr工程测试
如下可以测试solr下各各Field的索引和搜索的分词效果。
如下是solrcore的索引维护界面:
如下是SolrCore的搜索界面:
- 多SolrCore配置
一个solr工程可以通过多个solrcore分别对外提供索引和搜索服务。
每个solrCore单独对外提供http的索引和搜索服务,相关于一个mysql数据(Solr工程)运行了多个数据库(solrcore)
配置多SolrCore的好处:
1.一个solr工程对外通过SorlCore 提供服务,每个SolrCore相当于一个数据库,这个功能就相当于一个mysql可以运行多个数据库。
2.将索引数据分SolrCore存储,方便对索引数据管理维护。
3.SolrCloud集群需要使用多core。
修改collection2下的core.properties,如下:
删除data目录下的两个文件(因为是复制过来,所以需要删除);
修改conf目录下的solrconfig.xml中的如下属性:
Solr的基本使用
schema.xml
- Field和fieldType
schema.xml,在SolrCore的conf目录下,它是Solr数据表配置文件,它定义了加入索引的数据的数据类型的。主要包括FieldTypes、Fields和其他的一些缺省设置。
field:进行索引,需要创建document,document中包括 了很多的field(域)。
field属性:是否索引、是否存储、是否分词 ,是否多值multiValued
multiValued:该Field如果要存储多个值时设置为true,solr允许一个Field存储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和小图),通过使用solr查询要看出返回给客户端是数组:
Fieldtype:在solr中对每个Field都有一个Type类型。
在Solr中进行索引、搜索时需要用哪些field需要提前在schema.xml文件中定义!!!!
通过界面查看 solrCore中有哪些field被定义:
比如:
filed的name:name
indexed:是否索引,true表示要索引,索引的目的为了搜索
stored:是否存储,存储的目的是为了从索引文件读取数据
type:text_general
- 主键(重点)
Solr在维护索引时要根据主键进行维护,比如创建索引没有指定主键,报如下错误:
如何指定solr的主键:
在schema.xml配置id
Solr中默认定义唯一主键key为id域,如下:
Solr在删除、更新索引时使用id域进行判断,也可以自定义唯一主键。
注意在创建索引时必须指定唯一约束。
- copyField复制域
copyField复制域,可以将多个Field复制到一个Field中,以便进行统一的检索:
比如,输入关键字要搜索title标题和内容content这两个域时,要用到复制域
定义目标域:
必须要使用:multiValued=”true”
将以下的域复制到目标域中:
如果在搜索时,搜索text域,solr会分别从以上cat、name、manu、features、includes这域中搜索,类似lucene中组合 域 搜索。
- dynamicField
使用 solr时要定义很多field比较麻烦,可以定义一种动态域,动态域没有具体的域名是定义一个规则,比如:name 为*_i。
当创建索引,指定field名称匹配上规则solr就执行成功,比如:动态域*_i,只要以_i结尾 的就可以索引创建成功。 - 使用solrJ操作solr
**注意:记住核心类SolrServer,通过SolrServer进行操作
// 添加
@Test
public void testUpdateIndex() throws Exception {
// 创建一个Solr的服务对象---需要solr的路径
SolrServer solrServer = new HttpSolrServer(solrURL);
// 创建一个SolrInputDocument类型的文档
SolrInputDocument inputDocument = new SolrInputDocument();
// 给文档赋值--- 需要输入域名和对应的值
inputDocument.addField("id", "1");
inputDocument.addField("product_name", "lucene编程指南");
inputDocument.addField("product_price", 88.8f);
inputDocument.addField("product_catalog_name", "计算机编程");
inputDocument.addField("product_description", "lucene编程指南是一本非常有用的书!");
inputDocument.addField("product_picture", "373737722.jpg");
// 执行更新索引操作---需要一个SolrInputDocument类型的文档
UpdateResponse response = solrServer.add(inputDocument);
System.out.println(response);
// 提交
solrServer.commit();
}
数据导入处理器
- dataimport-Handler介绍
solr提供dataimport-Handler数据导入处理器,工作流程:
1、solr通过dataimport-Handler查询关系数据库中的数据
2、对查询到的数据创建索引
上边的过程是自动化完成的。
可以通过此dataimport-Handler,批量将关系数据库中的数据创建索引到solr索引库中。
- 实现步骤:
第一步:加载dataimport的jar包
将solr\dist\ solr-dataimporthandler-4.10.3.jar拷贝至solr\contrib\dataimporthandler
配置solrconfig.xml加载jar包:
第二步:加载mysql数据 驱动包
方法同上,将mysql数据库驱动的jar拷贝至solr\contrib\databaseDriver下
配置solrconfig.xml加载jar包:
第三步:配置dataimport导入数据
创建data-config.xml文件,存放在SolrCore的conf目录
此段代码需要根据情况进行修改
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/lucene"
user="root"
password="mysql"/>
<document>
<entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products ">
<field column="pid" name="id"/>
<field column="name" name="product_name"/>
<field column="catalog_name" name="product_catalog_name"/>
<field column="price" name="product_price"/>
<field column="description" name="product_description"/>
<field column="picture" name="product_picture"/>
</entity>
</document>
</dataConfig>
第四步:修改solrconfig.xml,添加requestHandler
<!--数据导入处理器-->
<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
- 测试数据导入
导入数据成功
solrj进行搜索
- solr的查询语法
1.q - 查询关键字,必须的,如果查询所有使用:。
请求的q是字符串
2.fq - (filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,例如::
请求fq是一个数组(多个值)
过滤查询价格从1到20的记录。
也可以在“q”查询条件中使用product_price:[1 TO 20],如下:
也可以使用“*”表示无限,例如:
20以上:product_price:[20 TO *]
20以下:product_price:[* TO 20]
3.sort - 排序,格式:field name desc/asc… 。示例:
按价格降序
4.start - 分页显示使用,开始记录下标,从0开始
5.rows - 指定返回结果最多有多少条记录,配合start来实现分页。
显示前10条。
6.fl - 指定返回那些字段内容,用逗号或空格分隔多个。
显示商品图片、商品名称、商品价格
7.df-指定一个搜索Field
也可以在SolrCore目录 中conf/solrconfig.xml文件中指定默认搜索Field,指定后就可以直接在“q”查询条件中输入关键字。
8.wt - (writer type)指定输出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我们,因为默认没有打开。
9.hl 是否高亮 ,设置高亮Field,设置格式前缀和后缀。
- 代码实现:
// 不指定solrCore,默认一个core
private static String solrUrl = "http://localhost:8080/solr";
// 指定solrCore名称
// private static String solrUrl = "http://localhost:8080/solr/collection1";
@Test
public void testSearchIndex() throws SolrServerException {
SolrServer solrServer = new HttpSolrServer(solrUrl);
//查询对象
SolrQuery query = new SolrQuery();
//查询语法
query.set("q", "product_name:天下");
//过虑
query.add("fq", "product_price:[0 TO 2]");
//query.add("fq", "product_catalog_name:另类文体");
//指定查询field
query.set("fl", "id,product_name");
//排序
query.addSort("product_name", ORDER.desc);
//分页信息
//每页显示个数
int pageSize=3;
//当前页码
int curPage=200;
//开始下标
int start = pageSize * (curPage-1);
query.setStart(start);
//每页显示个数
query.setRows(pageSize);
//高亮
query.setHighlight(true);//开启高亮组件
query.addHighlightField("product_name");//高亮字段
query.setHighlightSimplePre("<span color=red>");// 前缀标记
query.setHighlightSimplePost("</span>");// 后缀标记
//查询响应
QueryResponse response = solrServer.query(query);
//匹配文档
SolrDocumentList docs = response.getResults();
//匹配文档总数
long numFound = docs.getNumFound();
System.out.println("匹配文档总数:"+numFound);
//从响应中获取高亮信息
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
for(SolrDocument doc:docs){
//商品id
System.out.println("id:"+doc.get("id"));
//商品名称
System.out.println("product_name:"+doc.get("product_name"));
//商品价格
System.out.println("product_price:"+doc.get("product_price"));
//...
//取出高亮信息
if(highlighting!=null){
//根据id主键取出高亮信息
Map<String, List<String>> map = highlighting.get(doc.get("id"));
//取出高亮字段信息
List<String> list = map.get("product_name");
System.out.println("product_name高亮后:"+list.get(0));
}
}
}