了解Spring Data(二)之Solr搜索引擎
简介
Solr是来自Apache Lucene项目的流行,快速,开源的NoSQL搜索平台。其主要功能包括强大的全文搜索,点击突出显示,分面搜索,动态聚类,数据库集成,丰富的文档处理和地理空间搜索。Solr具有高度可扩展性,可提供容错的分布式搜索和索引,并为世界上许多最大的互联网站点提供搜索和导航功能。
Solr支持Lucene ,可在任何数据类型中实现强大的匹配功能,包括短语,通配符,连接,分组等功能。
我们常用的MySQL中的InnoDB存储引擎,它的索引的方式是根据一个字段的值完全匹配或者通过对某一个字段进行模糊查询的方式搜索,但是这样查询效率很低,且查询只能查询一个字段中与查询的关键字相似的数据,并不能查到所有与这个关键字相关的数据(比如其他字段中也有包含这个关键字,我还想要这些信息,那么InnoDB就做不到这些了)。像我们日常用到的搜索,比如谷歌、百度、淘宝的搜索、京东的搜索等等,这些搜索查询的结果并不都是你想要的数据,这就是搜索引擎的做到的。
安装
安装很简单,直接去官网下载压缩包就行(windows系统.zip
格式,Linux系统.tgz
格式)
传送门:Solr 8.1.1
简单使用
启动
单节点方式
在solr的安装路径下使用shift + 右键
中的在此处打开cmd窗口
(或者powershell窗口),打开命令窗口后使用windows命令(cmd):
bin\solr.cmd start
windows命令(powershell):
.\bin\solr.cmd start
Linux系统下的命令:
bin/solr start
这种方式启动的是solr的默认端口8983,如果启动其他端口可以再加一个参数
-p host
启动成功后命令行会出现一行Started Solr server on port 8983. Happy searching!
,此时可以打开浏览器输入http://localhost:8983
即可进入solr的可视化管理界面
[外链图片转存失败(img-AMSg9f0o-1564837364013)(C:\Users\召\AppData\Roaming\Typora\typora-user-images\1563976733180.png)]
集群方式
下面的home
目录是官方的给出的示例
windows命令(cmd):
bin\solr.cmd start
bin\solr.cmd start -p 7574 -s example\techproducts\solr -z localhost:9983
windows命令(powershell):
.\bin\solr.cmd start
.\bin\solr.cmd start -p 7574 -s .\example\techproducts\solr -z localhost:9983
Linux系统下的命令:
bin/solr start
bin/solr start -c -p 7574 -s example/techproducts/solr -z localhost:9983
-s
: 指定solr节点的home目录-z
: 指定zookeeper地址(如果以8983启动solr而不指定-z参数,solr会自动启动内置的zookeeper,并且将自身的端口号设置为9983)-c
:指定以集群模式启动solr-p
: 指定solr节点的端口号
启用官方示例
windows命令如下(cmd):
bin\solr.cmd start -e [example]
windows命令如下(shell):
.\bin\solr.cmd start -e [example]
Linux系统命令如下:
bin/solr start -e [example]
可用的example有:
- cloud: SolrCloud example
- techproducts: Comprehensive example illustrating many of Solr's core capabilities
- dih: Data Import Handler
- schemaless: Schema-less example
比如,以Linux命令为例:
bin/solr start -e cloud
命令输入完后,一直回车即可,直至出现SolrCloud example running, please visit: http://localhost:8983/solr
,然后使用浏览器访问该地址,会发现已经多出了一个集群和两个core
停止
停止命令语法:
solr stop [-k key] [-p port] [-V]
常用操作:
# 停止本机上的所有节点
bin/solr stop -all
或
# 停止指定端口节点
bin/solr stop -p 8983
**注:**solr stop时经过我多方查阅其他两个参数基本上不需要我们去指定(官方文档也没给出那两个参数有什么用),我们只需要指定
-p
或-all
参数即可
创建collection/core
单机版solr上的数据集叫做核心core
,集群版的solr上的数据集叫做collection
,我们执行下面的命令,会自动检测本机上的solr当前是单机模式还是集群模式,然后决定调用bin/solr create_core
(单机)还是bin/solr create_collection
(集群)
语法
solr create [-c name] [-d confdir] [-n configName] [-shards #] [-replicationFactor #] [-p port]
参数说明:
-c
:指定core或collection名称-d
: 指定配置目录-n
: 指定配置名称(如果不指定默认使用_default
)-shards
: 指定在几个节点上创建,默认是1(可以简写为-s
)-replicationFactor
: 指定每个节点上创建几个副本,默认是1,没有副本(可以简写为-rf
)-p
: 通过指定端口号确定要在那个节点上创建,如果不传solr会自动用找到的第一个节点
配置collection/core的schema
通过官方的Schema API
SchemaAPI是通过发起Restful请求的方式来操作Schema,如通过postman来发送一下请求:
手动修改配置文件
修改当前collection或者core主目录(server/{core}/
)下的conf/managed_schema
文件,添加需要的字段配置,如:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<!-- 下面的text_zh类型是后面添加的分词器 -->
<field name="title" type="text_zh" indexed="true" stored="true" required="false" multiValued="false" />
上面使用的是自定义的字段类型,而没有使用solr的**“无模式”和“字段类型推测”(就是不指定该字段的类型,可以让solr通过用户存入前几条数据的类型去推测你整张表的该字段的类型。这种方式一旦推测错误,数据完成索引后将无法做出修改。因此,只适合练手学习,不建议在生产环境使用)。不过,我们可以使用两种方式结合的方式简化solr,比如只根据业务和用户搜索习惯在schema中手动定义部分字段,剩下业务不相关的字段可以让solr”自动推测字段类型“**。
导入示例数据
导入示例数据需要有一个collection/core,下面以我的test
核心为例
Linux平台命令:
./bin/post -c test example/exampledocs/*
Windows平台命令:
java -jar -Dc=test -Dauto example\exampledocs\post.jar example\exampledocs\*
参数说明:
-c
:要将数据post到那个数据集中
使用搜索
基本查询
q
查询的关键字,此参数最为重要,例如,q=id:1
,默认为q=*:*
fl
指定返回哪些字段,用逗号或空格分隔,注意:字段区分大小写,例如,fl= id,title,sort
start
返回结果的第几条记录开始,一般分页用,默认0开始rows
指定返回结果最多有多少条记录,默认值为 10,配合start实现分页sort
排序方式,例如id desc 表示按照 “id” 降序,多个字段:score desc,price asc
wt
(writer type)指定输出格式,有xml
,json
,php
等fq
(filter query)过虑查询,提供一个可选的筛选器查询。返回在q查询符合结果中同时符合的fq条件的查询结果,例如:q=id:1&fq=sort:[1 TO 5]
,找关键字id为1 的,并且sort是1到5之间的。df
默认的查询字段,一般默认指定。qt
(query type)指定那个类型来处理查询请求,一般不用指定,默认是standard
。indent
返回的结果是否缩进,默认关闭,用indent=true|on
开启,一般调试json
,php
,phps
,ruby
输出才有必要用这个参数。- version 查询语法的版本,建议不使用它,由服务器指定默认值。
solr检索运算符
:
指定字段查指定值,如返回所有值*:*
?
表示单个任意字符的通配*
表示多个任意字符的通配(不能在检索的项开始使用*
或者?
符号)~
表示模糊检索,如检索拼写类似于”roam”的项这样写:roam~
将找到形如foam和roams的单词;roam~0.8
,检索返回相似度在0.8以上的记录。AND
、||
、OR
、&&
布尔操作符NOT
、!
、-
(排除操作符不能单独与项使用构成查询)+
存在操作符,要求符号+
后的项必须在文档相应的域中存在( )
用于构成子查询[]
包含范围检索,如检索某时间段记录,包含头尾,date:[201507 TO 201510]
{}
不包含范围检索,如检索某时间段记录,不包含头尾date:{201507 TO 201510}
配置中文分词器
官方提供的分词器
smartcn
这是一种简体中文的分词器,配置方法在schema文件中添加下面的配置:
<fieldType name="text_zh" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
<filter class="solr.CJKWidthFilterFactory"/>
<filter class="solr.StopFilterFactory"
words="org/apache/lucene/analysis/cn/smart/stopwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/>
<filter class="solr.CJKWidthFilterFactory"/>
<filter class="solr.StopFilterFactory"
words="org/apache/lucene/analysis/cn/smart/stopwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
icu
多种语言通用分词器,没用过不说了。
第三方分词器
ik
也没有用过,略过。。。
分词器配置方式
将分词器依赖包添加到solr类路径中
默认smartcn、icu分词器是在{solr-install-home}/contrib/analysis-extras/lucene-libs
下的,我们需要将其添加到solr识别的路径下
官方的方法是在solrconfig.xml文件中添加<lib>
标签(里面已经有一些默认配置了,复制一下,改改路径就行)
<lib dir="${solr.install.dir:../../../..}/contrib/extraction/analysis-extras/lucene-libs" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/extraction/analysis-extras/lib" regex=".*\.jar" />
但我配置完发现还是报类找不到,在google上找到另一个解决办法:在{solr-install-home}/server/
目录下新建一个lib
目录,然后将需要的jar包放进去就可以了,亲测有效
分词器配置
在managed-schema
文件(建议直接修改server/configsets/_default/conf
目录下的managed-schema
文件,相当于改了全局的配置)中添加fieldType
标签来引用我们添加的分词器。fieldType
标签具体配置内容见上面的各分词器说明
使用SolrJ客户端操作solr
SolrJ客户端整体操作很简单,主要分为数据导入Solr和通过Solr搜索数据两部分
导入数据到Solr,主要步骤
1、创建SolrClient对象
2、循环创建SolrInputDocument对象
3、通过SolrClient对象的add方法将第2步中创建的document添加进去
4、最后记得调用SolrClient对象的commit方法将数据提交到Solr服务器
简单的数据导入示例
// 从数据库中查询数据
List<Item> itemList = itemDao.findAll();
// 定义批量操作暂存队列
List<SolrInputDocument> batchList = new ArrayList<>();
for(int i = 0; i< itemList.size(); i++) {
//将对象转换为SolrInputDocument对象
Item item = itemList.get(i);
SolrInputDocument doc = new SolrInputDocument();
// 下面的两个字段是刚刚在schema中定义的字段(也是数据库中查询出的字段)
doc.addField("id", item.getId());
doc.addField("title", item.getTitle());
// 将创建好的待存的SolrInputDocument对象添加到批量暂存队列
batchList.add(doc);
// 批量添加到solrClient
if(batchList.size() % 500 == 0) {
System.out.println("批量导入solr500条");
solrClient.add(batchList);
batchList.clear();
}
}
// 提交剩下的数据
if(batchList.size() > 0) {
System.out.println("批量导入solr"+batchList.size()+"条");
solrClient.add(batchList);
batchList.clear();
}
// 提交到Solr服务器
solrClient.commit();
搜索数据,主要步骤:
1、创建SolrClient对象
2、构造SolrQuery对象
3、执行搜索
4、获取搜索结果
带排序和分页的搜索示例
我是使用的spring boot环境下执行的下面的代码,spring boot的配置文件中有solr的host
spring.data.solr.host=http://localhost:8983/solr/test
不使用springboot环境的可以使用下面注释掉的方式指定solr的host
@Autowired
private SolrClient solrClient;
@Test
public void testSolr() {
try {
// 不使用springboot方式的指定host
// SolrClient solr = new HttpSolrClient("http://localhost:8983/solr/test");
// 构造搜索条件
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("四火");
// 默认属性
solrQuery.set(CommonParams.DF,"keywords");
// 从第几页开始
solrQuery.set(CommonParams.START, 0);
// 一页显示多少条:默认为10
solrQuery.set(CommonParams.ROWS, CommonParams.ROWS_DEFAULT);
// 设置最高权重开启
solrQuery.setIncludeScore(true);
// 执行搜索
QueryResponse response = solrClient.query(solrQuery);
// 获取搜索结果
SolrDocumentList itemList = response.getResults();
// 处理搜索结果
System.out.println("最高匹配权值:" + itemList.getMaxScore());
System.out.println("总记录数: " + itemList.getNumFound());
System.out.println("搜索结果:");
for(SolrDocument item : itemList) {
for (String fieldName : item.getFieldNames()){
System.out.println(fieldName + ": " + item.getFieldValue(fieldName));
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (SolrServerException e) {
e.printStackTrace();
}
}
至此spring data中的solr的介绍就到此告一段落了,后续我会将springboot与mybatis的结合给大家总结一些要点,欢迎阅读。