Solr概述
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过Http Get操作提出查找请求,并得到指定格式的返回结果。
Solr安装部署
下载Solr
说明:Solr与Lucene是同步更新的,课程中使用4.10.3版本
解压Solr
目录结构说明:
bin:solr运行脚本
contrib:solr的一些扩展jar包,用于增强solr功能
dist:build过程中生成的war和jar文件,以及一些依赖文件
docs:solr的API文档
example:solr工程的例子目录
example/solr:标准的SolrHome,包含一个默认的SolrCore
example/webapps:包含了一个solr.war,该war可作为solr的运行示例工程,我们部署的solr服务就是用的它
licenes:solr相关的许可信息
安装环境
Solr本身集成了Jetty服务器,可以直接启动运行。 Tomcat、jetty、Jboss、underTow
打开cmd命令行窗口,进入solr解压目录中的example目录。
进行cmd执行:java -jar start.jar
虽然solr内置了Jetty服务器,但是在企业中一般使用Tomcat部署
需要环境:
Solr:4.10.3
JDK环境:1.8(solr4.10 要求jdk1.7以上版本)
服务器:Tomcat 8
配置SolrHome
SolrHome目录是solr服务运行的主目录。一个SolrHome目录包含有多个SolrCore。SolrCore目录中包含了运行solr实例的配置文件和数据文件(日志和索引文件)。每一个SolrCore提供独立的索引和搜索服务。
拷贝【资料\solr-4.10.3\example\solr】目录到【D:\solr】,重命名solr为solrhome
SolrHome目录:
SolrCore目录:
说明:
conf:SolrCore运行配置信息
data:SolrCore存放日志和索引文件的目录
core.properties:SolrCore的信息,比如:名称
配置SolrCore
配置SolrCore目录下的conf/solrconfig.xml文件:
说明:solrconfig.xml文件是配置SolrCore实例的相关信息。默认情况下可以不做修改。在企业项目中需要修改三个常用的标签:lib标签、datadir标签、requestHandler标签。
lib标签
在solrconfig.xml中可以加载一些扩展的jar,如果需要使用。(一般不需要使用)
solrconfig.xml文件75-85行,修改前:
datadir标签
配置SolrCore的data目录,data目录用来存放SolrCore的索引文件和tlog日志文件。solr.data.dir表示${SolrCore}目录,等价于${solr.install.dir}
说明:一般不需要修改。
requestHandler标签
requestHandler请求处理器,定义了索引和搜索的访问方式。
通过/select搜索索引,完成检索操作。
通过/update维护索引,可以完成索引的添加、修改、删除操作。
设置搜索参数完成搜索,搜索参数也可以设置一些默认值,如下:
explicit
10
text
Solr部署
准备Tomcat
修改Tomcat访问端口
部署solr.war
第1步
拷贝solr-4.10.3\example\webapps目录中的solr.war到tomcat的webapps目录中
复制到:
第2步
解压solr.war包:
第3步
【删除solr.war包】
说明:删除为了防止tomcat启动的时候,再进行解压,覆盖已经解压配置好的solr。
第4步
【加入solr服务扩展jar包】
solr-4.10.3\example\lib\ext目录下的所有jar包copy到部署到Tomcat中的solr的/WEB-INF/lib
把solr解压包下solr-4.10.3\example\lib\ext目录下的所有jar包拷贝到Tomcat部署的solr的WEB-INF/lib文件夹
复制到:
第5步
【准备log4j.properties日志文件】
把solr解压包下solr-4.10.3\example\resources\log4j.properties文件,复制到Tomcat的webapps\solr\WEB-INF\classes目录下(如果没有classes目录,创建一个):
第6步
【配置web.xml】
修改web.xml,配置SolrHome
打开env-entry注释,修改env-entry-value为solrHome目录。
第7步
【启动tomcat服务】
运行tomcat安装bin目录中的startup.bat文件:
Solr管理界面操作
Solr管理管理界面介绍
SolrCore介绍
选择一个SolrCore进行详细操作:
Analysis
通过此界面可以测试索引分析器和搜索分析器的执行情况
Dataimport
数据导入,从关系数据库将数据导入到Solr索引库中。默认没有配置,需要手工配置。
Documents
通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新。
删除文档:
1
Solr使用
schema.xml
schema.xml文件在SolrCore/conf目录。主要用于配置域的类型(FieldType)和配置域(Field)。在solr中域要先配置再使用。
Field
作用:配置域。
required="true" multiValued="false"/>
name:域的名称
type:域的类型
indexed:是否索引
stored:是否存储
required:是否必须(如果为true添加索引的时候,文档对象中必须要包含该域)
mulitValued:是否多值(用于复制域)
DynamicField
作用:配置动态域
name:动态域的名称
UniqueKey
作用:指定唯一约束域,相当于关系数据库中的主键id
说明:在solr中,唯一约束域是必须的。
CopyField
作用:配置复制域
source:源域的名称
dest:目标域的名称
说明:在solr中,允许将多个域的值复制给一个域,这样的目的是方便执行搜索。solr在创建索引的时候,会把源域的内容复制给目标域。(目标域的定义必须要包含一个属性:multiValued="true")
FieldType
作用:配置域的类型
name:域的类型名称
class:域的类型,solr中的类型
analyzer:指定分词器,index是索引流程;query是检索流程
tokenizer:具体使用的分词器
filter:具体使用的过滤器
配置IK分词器
说明:配置ik中文分词器。
拷贝IK分词器jar包
拷贝Maven仓库中的jar包:
拷贝到solr/WEB-INF/lib目录:
拷贝IK分词器配置文件
拷贝IK解压目录中的配置文件
拷贝到solr/WEB-INF/classes目录:
配置schema.xml
通过FieldType标签,配置使用IK分词器的域类型
通过Field标签,配置使用IK分词器的域
stored="true" multiValued="false"/>
重启tomcat
5.3配置业务域
说明:使用solr实现商品数据的搜索,需要把保存在关系数据库中的商品数据,导入solr索引库。
5.3.1准备商品数据
导入goods.sql
商品编号(商品编号是主键,作为唯一约束域uniqueKey):
required="true"/>
商品名称:
商品标题:
商品价格:
商品图片:
定义商品复制域(在实际项目中复制域不需要存储,这里存储是为了给大家看到数据效果):
把商品名称和商品标题添加到复制域
5.3.3配置schema.xml<?xml version="1.0" encoding="UTF-8" ?>
multiValued="true"/>
id
5.3.4配置solrconfig.xml 默认域
更改默认域名称,改成我们的域名称:
5.4 配置数据导入
5.4.1拷贝数据导入jar包
拷贝solr解压目录dist目录中的jar包:
拷贝到solr/solrHome/lib(lib手动创建):
5.4.2拷贝数据库驱动jar包
拷贝到solr/solrhome/lib:
5.4.3配置solrconfig.xml
第1步
配置lib标签,加载jar包
第2步
通过requestHandler标签,配置数据导入的请求处理器
import-config.xml
第3步
创建import-config.xml
<?xmlversion ="1.0" encoding="UTF-8"?>
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/lucene_db"
user="root"
password="admin"/>
query="SELECT id,name,title,price,pic FROM goods">
5.4.4重启tomcat,执行导入
查询数据
Solr管理界面搜索
q: 指定查询表达式
`*:*`:表示搜索全部
name:商务,表示搜索name域中包含有“商务”
fq:指定搜索的过滤条件
price:[2000 TO 8000],表示搜索2000 至8000之间的商品,包含2000 ,包含8000
price:{2000 TO 8000},表示搜索2000 至8000之间的商品,不包含2000 ,不包含8000
sort:指定搜索结果排序
price asc,表示按照商品价格升序排序
price desc,表示按照商品价格降序排序
start,rows:指定分页
start:分页开始记录数
rows:每页显示记录数
fl:指定搜索结果显示的域列表
pid,name,price,显示商品id、商品名称、商品价格
df:指定默认搜索域
注意事项:默认搜索域只能指定一个。
wt:指定搜索结果的响应格式
常用格式:json/xml/csv。
hl:指定高亮显示
hl.fl:指定高亮显示的域名称
hl.simple.pre:指定高亮显示的html标签的开始部分
hl.simple.post:指定高亮显示的html标签的结束部分
注意:高亮结果集的数据结构为:`Map>`
Solrj
Solrj是什么
SolrJ是一个使Java应用程序可以轻松与Solr对话的API。SolrJ隐藏了许多连接到Solr的细节,并允许您的应用程序通过简单的高级方法与Solr进行交互。
SolrJ的中心是org.apache.solr.client.solrj包,它只包含五个主要的类。首先创建一个SolrClient代表你想要使用的Solr实例。然后发送SolrRequests或SolrQuerys找回SolrResponses。
需求
使用solrj访问solr服务,完成索引的增删改查操作。
6.3 需求实现
6.3.1 创建Maven项目
配置依赖<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.dfbz
Solr
1.0-SNAPSHOT
org.apache.solr
solr-core
4.10.3
commons-logging
commons-logging
1.1.3
junit
junit
4.12
代码实现
添加(更新)索引
说明:solr是根据pid域执行索引的更新。先根据pid域执行搜索,搜索到执行更新;搜索不到执行添加。
创建HttpSolrServer对象,连接solr服务
创建域相关的实体对象(Product)
使用HttpSolrServer对象,执行添加(更新)
提交事务
第一步:创建域相关的实体类package com.dfbz.entity;
import org.apache.solr.client.solrj.beans.Field;
public class Goods {
@Field("id")
private String id;
@Field
private String name;
@Field
private String title;
@Field
private Double price;
@Field
private String pic;
}package com.dfbz.solr;
import com.dfbz.entity.Goods;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class Demo1 {
private HttpSolrServer solrServer = new HttpSolrServer("http://localhost:8983/solr/collection1");
@Test
public void saveOrUpdate() throws IOException, SolrServerException {
Goods goods = new Goods();
goods.setId("888");
goods.setName("东标方准牌手机");
goods.setTitle("东标方准牌手机,好吃不上火!");
goods.setPrice(9999.99);
//如果没有则添加,如果有则修改
solrServer.addBean(goods);
//提交事务
solrServer.commit();
}
}
注意:在solr中,添加和修改是同一个方法,如果id存在则修改,如果id不存在则添加
删除索引
根据id删除:
创建HttpSolrServer对象,连接solr服务
使用HttpSolrServer对象执行删除
提交事务/** 根据id删除索引 */
@Test
public void deleteById() throws Exception{
solrServer.deleteById("888");
// 提交事务
solrServer.commit();
}
根据条件删除
创建HttpSolrServer对象,连接solr服务
使用HttpSolrServer对象,执行删除
提交事务//根据条件删除
@Test
public void deleteByQuery() throws IOException, SolrServerException {
solrServer.deleteByQuery("title:手机");
solrServer.commit();
}
查询索引
创建HttpSolrServer对象,连接solr服务
创建查询对象(SolrQuery),封装查询条件
使用HttpSolrServer对象执行搜索,返回QueryResposne对象
通过QueryResponse对象中获取查询的结果
处理结果//条件查询
@Test
public void query() throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("title:商务");
QueryResponse response = solrServer.query(solrQuery);
System.out.println("数量: " + response.getResults().getNumFound());
List goodsList = response.getBeans(Goods.class);
for (Goods goods : goodsList) {
System.out.println(goods);
System.out.println("-------------------");
}
}
查询步骤:
创建HttpSolrServer对象,连接solr服务
创建查询对象(SolrQuery),封装查询条件
使用HttpSolrServer对象执行搜索,返回QueryResponse
通过QueryResponse获取搜索结果
通过QueryResponse获取高亮内容
处理搜索结果及高亮内容//复杂条件查询
@Test
public void query2() throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery("title:手机");
//添加过滤条件
solrQuery.addFilterQuery("price:[1000 TO 9000]");
//排序
solrQuery.addSort("price", SolrQuery.ORDER.desc);
//分页
solrQuery.setStart(0);
solrQuery.setRows(10);
//设置查询域
solrQuery.setFields("id,price,name,title");
//开启高亮
solrQuery.setHighlight(true);
//高亮域
solrQuery.addHighlightField("title");
solrQuery.setHighlightSimplePre("");
solrQuery.setHighlightSimplePost("");
QueryResponse response = solrServer.query(solrQuery);
System.out.println("查询到的条数: " + response.getResults().getNumFound());
//获取查询数据
List goodsList = response.getBeans(Goods.class);
//获取高亮数据
Map>> high = response.getHighlighting();
for (Goods goods : goodsList) {
//根据id查询到对应高亮数据(map);查询title的值
System.out.println("id: " + goods.getId() + " title: " + high.get(goods.getId()).get("title"));
;
}
}
set复杂查询//set查询
@Test
public void query3() throws IOException, SolrServerException {
SolrQuery solrQuery = new SolrQuery();
//设置全局查询
solrQuery.set("q","小米");
//设置FilterQuery
solrQuery.set("fq", "price:[0 TO 8000]");
//设置起始页数
solrQuery.set("start", 0);
//设置页大小
solrQuery.set("rows", 5);
//设置排序规则
solrQuery.set("sort", "price desc");
//设置FieldList
solrQuery.set("fl", "id,name,price");
//设置默认域
solrQuery.set("df", "keywords");
//开启高亮
solrQuery.setHighlight(true);
//设置高亮域
solrQuery.addHighlightField("title");
//设置高亮域
solrQuery.addHighlightField("name");
//高亮前缀
solrQuery.setHighlightSimplePre("");
//高亮后缀
solrQuery.setHighlightSimplePost("");
//执行查询
QueryResponse response = solrServer.query(solrQuery);
System.out.println("记录数: " + response.getResults().getNumFound());
List goodsList = response.getBeans(Goods.class);
System.out.println("查询数据: ");
for (Goods goods : goodsList) {
System.out.println(goods);
}
System.out.println("----------------------");
System.out.println("高亮数据: ");
Map>> high = response.getHighlighting();
for (Goods goods : goodsList) {
String name = high.get(goods.getId()).get("title").get(0);
String title = high.get(goods.getId()).get("name").get(0);
System.out.println("name: " + name + ";title: " + title);
}
}