Solr
1. Solr基本
1.1. Solr简介
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。
1.2. Solr安装
# 解压solr压缩包
tar zxvf solr-8.11.0.tgz
- bin:可执行文件所在目录
- dist:Solr对歪提供的核心、拓展、插件等代码的jar文件
- server:Solr搜索应用服务器核心目录
- server/solr:Solr的索引库所在位置
- server/solr-webapp:Solr的WAR核心应用
- server/etc:Solr的核心配置
1.3. 修改启动参数
# 进入bin目录
cd /usr/local/solr/solr-8.11.0/bin
# 修改启动脚本文件
vim solr.in.sh
# 修改启动参数 否则启动时报警告
# 搜索引擎 不使用Root用户进行启动
SOLR_ULIMIT_CHECKS=false
1.4. 启动Solr
- 启动solr
# Solr不推荐使用root账户启动 如果是root 要加-force参数
# Solr内置Netty服务器 默认启动端口是 8983
./solr start -force
# 启动Solr #
[root@Mashiro bin]# ./solr start -force
Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
NOTE: Please install lsof as this script needs it to determine if Solr is listening on port 8983.
Started Solr server on port 8983 (pid=27697). Happy searching!
- 访问web
http://127.0.0.1:8983
- web显示界面
- Dashboard:控制台信息
- Logging:日志展示
- Security:
- Core Admin:索引库
- Java Properties:Java相关配置
- Thread Dump:线程信息
1.5. 创建索引库
# 进入server目录
[root@Mashiro solr-8.11.0]# cd server
# 进入solr目录
[root@Mashiro server]# cd solr
# 创建索引库目录
[root@Mashiro solr]# mkdir test
# 进入配置目录
[root@Mashiro solr]# cd /configsets/_default
# 将配置目录下的conf目录 复制到 创建的索引库 目录中
[root@Mashiro solr]# cp -r configsets/_default/conf test
- 前往Web创建索引库
- 创建完成
- 索引库下拉框目录
1.6. 安装中文分词器
# 1. 下载中文分词器jar包
https://search.maven.org/search?q=com.github.magese
# 2. 进入lib目录
[root@Mashiro solr-8.11.0]# cd server/solr-webapp/webapp/WEB-INF/lib/
# 3. 将中文分词器的jar包 放入 lib目录下
# 4. 修改 /test/conf/managed-schema 配置文件
[root@Mashiro conf]# vim managed-schema
# 5. 重启solr
[root@Mashiro solr-8.11.0]# bin/solr stop -all
[root@Mashiro solr-8.11.0]# bin/solr start -force
- 配置文件内容
<!-- ik分词器 -->
<field name="zh_all" type="text_ik_all" indexed="true" stored="true"/>
<field name="zh_smart" type="text_ik_smart" indexed="true" stored="true"/>
<fieldType name="text_ik_all" 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="false" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="text_ik_smart" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" 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>
2. managed-schema配置
2.1. < fieldType />
-
表示定义一个属性类型。在Solr中属性类型都是自定义得。
-
name=“xxx” 为自定义类型。
-
当某个属性取值为 xxx 时 分词器才能生效
2.2. < field />
- 表示向 Document 中添加一个属性
- name:属性名
- type:属性类型
2.3. < uniqueKey />
- 唯一主键,Solr中默认定义id属性为唯一主键。ID的值是不允许重复的。
2.4. < dynamicField >
- 名称中允许 * 进行统配。代表满足特定名称要求的一组属性。
3. 数据操作
3.1. 新增和修改 /update
- 唯一值(id)如果存在则为修改,不存在则为新增
<doc>
<field name="id">3</field>
<field name="zh_all">印度</field>
<field name="zh_smart">印度</field>
</doc>
3.2. 删除
<delete><query>zh_all:印度</query></delete>
<commit/>
3.3. 查询 /select
-
q: * : * (字段:值)
-
sort: 排序
-
start,rows: 分页
-
hl: 高亮
4. 数据导入
4.1. 配置
- (可选) 修改Schema
- 修改solrconfig.xml
<requestHandler name="dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">dataimport.xml</str>
</lst>
</requestHandler>
- DB --> select --> update --> solr
[root@Mashiro conf]# vim dataimport.xml
<?xml version="1.0" encoding="UTF-8">?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/test"
user="root"
password="123456">
<document>
<entity name="testEntity" query="select id, name from testTable">
<field column="id" name="id"/>
<field column="name" name="zh_all"/>
</entity>
</document>
</dataSource>
</dataConfig>
-
solr的lib目录下导入mysql驱动包和dataImportHandler的包
-
重启solr
5. SolrJ
5.1. 导入依赖
- 依赖的版本要与Solr的版本对应
<!-- https://mvnrepository.com/artifact/org.apache.solr/solr-solrj -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.6.0</version>
</dependency>
5.2. 查询
package com.mashiro.solr;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import java.io.IOException;
/**
* @description: 测试SolrJ Demo
* @author: mashiro
* @date: 2021/11/29
*/
public class Test {
/**
* select操作
*
*/
public static void select() {
// Solr访问地址 和 索引库
// ip port 应用名 索引库
String basePath = "http://127.0.0.1:8983/solr/test";
// 建造者模式 创建Solr客户端
HttpSolrClient client = new HttpSolrClient.Builder(basePath).build();
SolrQuery query = new SolrQuery();
// 查询条件
query.setQuery("*:*");
// 分页
query.setStart(0);
query.setRows(10);
// 排序
query.setSort("id", SolrQuery.ORDER.desc);
// 开启高亮
query.setHighlight(true);
// 设置高亮字段
query.addHighlightField("zh_all");
// 设置高亮前缀
query.setHighlightSimplePre("<span style='color:red'>");
// 设置高亮后缀
query.setHighlightSimplePost("</span>");
try {
QueryResponse queryResponse = client.query(query);
System.out.println(queryResponse);
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.3. 新增 & 修改
/**
* update操作
*
* 主键存在 则为修改
* 主键不存在 则为新增
*/
public static void update(){
// Solr访问地址 和 索引库
// ip port 应用名 索引库
String basePath = "http://127.0.0.1:8983/solr/test";
// 建造者模式 创建Solr客户端
HttpSolrClient client = new HttpSolrClient.Builder(basePath).build();
// Solr新增数据的对象
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id","123456");
doc.addField("zh_all","TestSolrJ");
try {
UpdateResponse response = client.add(doc);
System.out.println("SolrJ 响应状态 ==> " + response.getStatus());
} catch (SolrServerException e) {
// 遇到异常 执行回滚操作
try {
client.rollback();
} catch (SolrServerException solrServerException) {
solrServerException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
} catch (IOException e) {
// 遇到异常 执行回滚操作
try {
client.rollback();
} catch (SolrServerException solrServerException) {
solrServerException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
// 执行成功 提交事务
try {
client.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 回收资源
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
5.4. 删除
/**
* delete操作
*
*/
public static void delete() {
// Solr访问地址 和 索引库
// ip port 应用名 索引库
String basePath = "http://127.0.0.1:8983/solr/test";
// 建造者模式 创建Solr客户端
HttpSolrClient client = new HttpSolrClient.Builder(basePath).build();
try {
// 删除现象
UpdateResponse response = client.deleteById("123456");
System.out.println("SolrJ 响应状态 ==> " + response.getStatus());
} catch (SolrServerException e) {
// 遇到异常 执行回滚操作
try {
client.rollback();
} catch (SolrServerException solrServerException) {
solrServerException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
} catch (IOException e) {
// 遇到异常 执行回滚操作
try {
client.rollback();
} catch (SolrServerException solrServerException) {
solrServerException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
// 执行成功 提交事务
try {
client.commit();
} catch (SolrServerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 回收资源
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
6. Spring Data
6.1. 导入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.13.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
</dependencies>
6.2. 配置文件
spring:
data:
solr:
host: http://127.0.0.1:8983/solr
6.3.创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@SolrDocument
public class TestSolrBean {
@Id
@Field("id")
private Long id;
@Field("zh_all")
private String zhAll;
}
6.4. 测试Update
/**
* 保存JavaBean的方法(单一保存和批量保存)
* solrTemplate.saveBean(String collection, Object obj);
* solrTemplate.saveBeans(String collection, List<Object> objs);
*
* 保存Solr Document的方法(单一保存和批量保存)
* solrTemplate.saveDocument(String collection, SolrInputDocument doc);
* solrTemplate.saveDocuments(String collection, List<SolrInputDocument> docs);
*/
@Test
public void testUpdate() {
TestSolrBean bean1 = new TestSolrBean(100L, "测试SolrTemplate100");
TestSolrBean bean2 = new TestSolrBean(200L, "测试SolrTemplate200");
TestSolrBean bean3 = new TestSolrBean(300L, "测试SolrTemplate300");
ArrayList<TestSolrBean> beans = new ArrayList<TestSolrBean>();
beans.add(bean1);
beans.add(bean2);
beans.add(bean3);
UpdateResponse response = solrTemplate.saveBeans("test", beans);
solrTemplate.commit("test");
System.out.println(response);
}
6.5. 测试 Query
@Test
public void testQuery() {
// Spring Data 通用条件模板
Criteria criteria = Criteria.where("zh_all").is("测试");
Query que = Query.query(criteria);
// 排序
que.addSort(Sort.by(Sort.Direction.DESC, "id"));
// 分页
que.setPageRequest(PageRequest.of(0,10));
// 排序和分页可以进行连写
// que.setPageRequest(PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC)));
ScoredPage<TestSolrBean> result = solrTemplate.queryForPage("test", que, TestSolrBean.class);
System.out.println(result.getContent());
}
6.6. 测试 Delete
@Test
public void testDelete() {
UpdateResponse response = solrTemplate.deleteByIds("test", "100");
solrTemplate.commit("test");
System.out.println(response);
}
6.7. 测试高亮查询
@Test
public void testHighLightQuery() {
SimpleHighlightQuery highlightQuery = new SimpleHighlightQuery();
// 设置条件
highlightQuery.addCriteria(Criteria.where("zh_all").is("测试"));
// 设置高亮字段与前后缀
HighlightOptions options = new HighlightOptions();
options.addField("zh_all");
options.setSimplePrefix("<em>");
options.setSimplePostfix("</em>");
highlightQuery.setHighlightOptions(options);
HighlightPage<TestSolrBean> test = solrTemplate.queryForHighlightPage("test", highlightQuery, TestSolrBean.class);
List<TestSolrBean> content = test.getContent();
List<HighlightEntry<TestSolrBean>> list = test.getHighlighted();
for (HighlightEntry<TestSolrBean> entry : list) {
// 获取高亮字符数组
for (HighlightEntry.Highlight highlight : entry.getHighlights()) {
System.out.println(highlight.getSnipplets());
}
// 获取查询结果对象
System.out.println(entry.getEntity());
}
}