Solr的基础配置和应用
Solr是一个高性能,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。
Lucene
Lucene是apache jakarta项目的一个子项目,是一个开放源代码的全文检索引擎开发工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
倒排索引
Solr用的是倒排索引
正排:
我们先找到文档,然后再在文档中找出包含的词,确定关键词的出现次数,位置等信息
倒排:
把所有文档先进行分词,然后根据查询条件,去匹配文档
测试依赖
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>8.1.1</version>
</dependency>
<--这个是smartcn,Lucene自带的分词工具,不太好用-->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>8.1.1</version>
</dependency>
测试分词
public class Test1 {
String[] a = {
"3, 华为 - 华为电脑, 爆款",
"4, 华为手机, 旗舰",
"5, 联想 - Thinkpad, 商务本",
"6, 联想手机, 自拍神器"
};
@Test
public void test1() throws Exception {
//存储索引文件的路径
File path = new File("d:/abc/");
FSDirectory d = FSDirectory.open(path.toPath());
//lucene提供的中文分词器
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
//通过配置对象来指定分词器
IndexWriterConfig cfg = new IndexWriterConfig(analyzer);
//索引输出工具
IndexWriter writer = new IndexWriter(d, cfg);
for (int i = 0; i < a.length; i++) {
String[] strs = a[i].split(",");
//创建文档,文档中包含的是要索引的字段
Document doc = new Document();
doc.add(new LongPoint("id", Long.parseLong(strs[0])));
doc.add(new StoredField("id", Long.parseLong(strs[0])));
doc.add(new TextField("title", strs[1], Store.YES));
doc.add(new TextField("sellPoint", strs[2], Store.YES));
//将文档写入磁盘索引文件
writer.addDocument(doc);
}
writer.close();
}
}
可以用Lucene
里面的luck工具查看索引信息
下面是查看分词的代码:
@Test
public void test2() throws Exception {
//索引数据的保存目录
File path = new File("d:/abc");
FSDirectory d = FSDirectory.open(path.toPath());
//创建搜索工具对象
DirectoryReader reader = DirectoryReader.open(d);
IndexSearcher searcher = new IndexSearcher(reader);
//关键词搜索器,我们搜索 "title:华为"
TermQuery q = new TermQuery(new Term("title", "华为"));
//执行查询,并返回前20条数据
TopDocs docs = searcher.search(q, 20);
//遍历查询到的结果文档并显示
for (ScoreDoc scoreDoc : docs.scoreDocs) {
Document doc = searcher.doc(scoreDoc.doc);
System.out.println(doc.get("id"));
System.out.println(doc.get("title"));
System.out.println(doc.get("sellPoint"));
System.out.println("--------------");
}
}
Solr的Linux安装和配置
下载的solr-?.?.?.tgz
上传到服务器
执行解压(tar -zxf
)
启动Solr
# 不建议使用管理员启动 solr,加 -force 强制启动
bin/solr start -force
# 开放 8983 端口
firewall-cmd --zone=public --add-port=8983/tcp --permanent
firewall-cmd --reload
当然,可以直接关闭防火墙,则不需要重新开端口了
可以直接在浏览器访问http://192.168.64.170:8983
进入控制台
控制台配置
Solr是通过core来保存索引数据的,所以我们需要首先在控制台创建一个core,这里创建一个名为pd的core
创建核心后,我们需要在服务器创建目录结构:
mkdir -p server/solr/pd/conf
mkdir -p server/solr/pd/data
conf
文件是存放配置文件的
把Solr提供的默认配置复制到我们的conf
目录
cp -r server/solr/configsets/_default/conf server/solr/pd
这个时候就可以在控制台测试基础的分词了
分词工具:ik-analyzer
项目地址:https://github.com/magese/ik-analyzer-solr
ik分词器的jar文件需要放到以下目录(固定)
server/solr-webapp/webapp/WEB-INF/lib
需要创建ik的配置目录:
# classes目录如果不存在,需要创建该目录
mkdir server/solr-webapp/webapp/WEB-INF/classes
这6个文件复制到 classes 目录下
resources/
IKAnalyzer.cfg.xml
ext.dic
stopword.dic
stopwords.txt
ik.conf
dynamicdic.txt
Solr配置ik分词器
修改server/solr/pd/conf/managed-schema
这个配置文件,添加 ik-analyzer 分词器
<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
配置之后需要重启Solr服务
cd /usr/local/solr-8.1.1
bin/solr restart -force
配置好了之后,我们及就可以在控制台的FieldType
中找到text_ik
选项,使用ik分词器了
ik分词器的停止词配置
在server/solr-webapp/webapp/WEB-INF/classes
目录下有一个stopword.dic
文件,里面存放的就是停止词,可以自行配置,配置后需要重启服务
Solr连接mysql数据库:Data Import Handler
1.在mysql中创建用户,配置权限,mysql8中的配置有所不同,这里的是老版本的配置:
grant all on *.* to 'root'@'%' identified by 'root';
2.我们需要把缺少的jar包到lib目录中:server/solr-webapp/webapp/WEB-INF/lib
mysql-connector-java-5.1.46.jar
solr-dataimporthandler-8.1.1.jar
solr-dataimporthandler-extras-8.1.1.jar
3.在控制台页面设置字段,对应sql表中的字段,并为每个字段配置格式,需要查询的字段格式设置为:text_ik
4.可以为默认字段_text_
绑定副本字段,需要在控制台页面通过Add Copy Field进行配置
5.配置连接信息
文件位置:server/solr/pd/conf/solrconfig.xml
在该文件最后加入:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">dih-config.xml</str>
</lst>
</requestHandler>
文件dih-config.xml
放在同目录下:
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://192.168.64.1:3306/pd_store"
user="root"
password="root"
batchSize="100"
autoCommit="false" />
<document name="item">
<entity name="item" pk="id"
query="SELECT id,title,sell_point sellPoint,price,barcode,image,cid,`status`,created,updated FROM pd_item"
deltaQuery="SELECT id,title,sell_point sellPoint,price,barcode,image,cid,`status`,created,updated FROM pd_item WHERE updated > date_add(str_to_date('${dih.last_index_time}','%Y-%m-%d %H:%i:%s'),interval 8 hour)"
transformer="RegexTransformer">
</entity>
</document>
</dataConfig>
配置完成后,重启Solr,即可在控制台页面测试是否能够导入数据
查询语法:
title:电脑 – 在title字段中查询电脑
电脑 – 在_text_
字段中查询电脑
“电脑” – 在_text_
字段中查询电脑,且电脑这个词不会被分割
+lenovo +电脑 – 同时满足条件
+lenovo -电脑 – 包含和不包含
如果需要统计,需要勾选上facet,并且在facet.field中填写需要统计的字段名
表达式:
勾选facet后,在Raw Query Parameters中输入:facet.mincount=50,facet.field填写字段,会筛选大于50的记录
价格范围:
Raw Query Parameters
中输入表达式:
facet.range=price&facet.range.start=0&facet.range.end=10000&facet.range.gap=2000
多字段统计:
facet.pivot=cid,status
整合Solr
依赖和yml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
yml:
spring:
data:
solr: #注意修改ip地址
host: http://192.168.64.170:8983/solr/pd
实体类Entity:
import org.apache.solr.client.solrj.beans.Field;
@Data
public class Item implements Serializable {
private static final long serialVersionUID = 1L;
@Field("id")
private String id;
@Field("title")
private String title;
@Field("sellPoint")
private String sellPoint;
@Field("price")
private Long price;
@Field("image")
private String image;
}
业务实现:
@Service
public class SearchServiceImpl implements SearchService {
/*
* SolrClient实例是在 SolrAutoConfiguration 类中创建的
*
* SolrAutoConfiguration添加了@Configuration注解,
* 是spring boot自动配置类,其中的solrClient()方法中创建了SolrClient实例
*/
@Autowired
private SolrClient solrClient;
@Override
public List<Item> findItemByKey(String key) throws Exception {
//封装查询的关键词
//也可以封装其他的查询参数,比如指定字段,facet设置等
SolrQuery query = new SolrQuery(key);
//查询前多少条数据
query.setStart(0);
query.setRows(20);
//执行查询并得到查询结果
QueryResponse qr = solrClient.query(query);
//把查询结果转成一组商品实例
List<Item> beans = qr.getBeans(Item.class);
return beans;
}
}