Spring Boot + Solr,solr中的修改启动
一.首先下载solr
下载路径:http://archive.apache.org/dist/lucene/solr/8.5.0/
中文分词器下载:在中央仓库中下载对应的版本 ik-analyzer-8.5.0.jar
二.本地安装solr
1.解压solr压缩包
1). bin 目录:可执行文件所在目录
2). dist 目录:solr对外提供的核心、扩展、插件等代码jar文件
3). server 目录:solr搜索应用服务器核心目录
4). server/solr 目录:solr的索引库所在位置
5). server/solr-webapp:solr的war核心应用
6). server/etc:solr的核心配置
2.修改启动参数(Linux下需要修改)
solr默认不推荐使用root用户启动,修改配置信息的目的是减少一些警告信息,不修改配置也可以(elasticsearch直接就是不允许root用户启动)
搜索引擎:目的是高效,要做大量的分析,写数据分析,查数据分析,在海量数据中模糊查询,是一个高并发、多线程的应用;
而root用户是一个没有权限限制的用户,可以无限的创建子线程,内存会被占满。
solr中的修改启动参数是在 solr-8.5.0\bin 目录下的 solr.in.sh 文件中,将 SOLR_ULIMIT_CHECKS=false (在207行)
3.启动solr
在当前目录下访问cmd 即 E:\config\solr\solr-8.5.0\bin
在进入bin目录启动 solr.cmd start
在Linux下启动 ./solr start -force (solr默认不推荐root账号启动,如果是root账号启动需要添加 -force 参数,如果不是root账号,则不需要添加 -force 参数)
启动后,在浏览器可以访问 http://localhost:8983/
4.创建自己的索引库
然后进入安装目录下的 E:\config\solr\solr-8.5.0\server\solr
创建自己的索引库 (文件夹my_solr_core)
添加索引库的配置文件
将 E:\config\solr\solr-8.5.0\server\solr\configsets_default 目录下的 conf 文件夹拷贝到索引库中
即拷贝到 E:\config\solr\solr-8.5.0\server\solr\my_solr_core 文件夹中
5.添加索引库
在可视化窗口中添加 core(添加索引库) 即在core admin 下添加
只修改 name 和 instanceDir
其中 name 随便定义(建议和自己创建的索引库名称一致)
instanceDir 就是我们创建的文件夹(my_solr_core)
其他的都不动点击确定
说明:instanceDir 是在 solr_home 中找文件夹,这里的 solr_home 的路径实际上就是 E:\config\solr\solr-8.5.0\server\solr
6.选择索引库
点击左侧菜单 core Selector (最下面的下拉)选择索引库
Dataimport 导入索引库
Documents 文档操作(增删改)
Query 查
Replication 备份
Schema 索引库字段
7.添加中文分词器
添加中文分词器jar(ik-analyzer-8.5.0.jar)
直接上传到 E:\config\solr\solr-8.5.0\server\solr-webapp\webapp\WEB-INF\lib 下即可
使用的时候需要修改配置文件
E:\config\solr\solr-8.5.0\server\solr\my_solr_core\conf 下的 managed-schema 文件
在跟标记第一层的子标签定义中文分词器
<!-- 配置定义域 -->
<field name="zh_ik" type="my_zh_ik" indexed="true" stored="true" multiValued="false" />
<!-- 添加中文分词器 -->
<fieldType name="my_zh_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>
相关解释:
name:字段名
type:类型
indexed:是否创建反向索引(就是将数据进行分析变成一个个单词存到索引里)
stored:是否保存该数据
required:是否必须
multiValued:是否是多个值(多值指的是字段是否是数组)
docValues:文档是否有具体值
useSmart:是否使用简化版本(就是尽可能的简单分析)
8.记一次报错
如果在上面的配置中添加了 required=“true” 则在导入的时候会导入失败
<field name="zh_ik" type="my_zh_ik" indexed="true" stored="true" required="true" multiValued="false" />
配置完成之后保存,并关闭,cmd下执行 solr stop -all
9.实现数据批量导入
修改 managed-schema 配置,是可选的(即:如果字段够用,则不需要修改,如果不够用,则需要增加字段)
修改 solrconfig.xml 配置,该文件是提供的是所有的solr服务对外提供的功能 E:\config\solr\solr-8.5.0\server\solr\my_solr_core\conf
配置数据库信息及查询语句
修改 solrconfig.xml 配置,在最后添加
<!-- 配置批量导入数据 -->
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
然后再当前目录下新建文件 data-config.xml (即在 E:\config\solr\solr-8.5.0\server\solr\my_solr_core\conf 目录下新建)
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&allowMultiQueries=true&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull"
user="root"
password="root"/>
<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>
说明:在上面的配置中注意 url 路径,参数要用 ‘&’ 分割,否则会报错
添加 mysql 驱动包到 E:\config\solr\solr-8.5.0\server\solr-webapp\webapp\WEB-INF\lib
即: mysql-connector-java-8.0.22.jar 上传
添加 DataImportHandler 所在的包到 E:\config\solr\solr-8.5.0\server\solr-webapp\webapp\WEB-INF\lib
即:solr-dataimporthandler-8.5.0.jar 和 solr-dataimporthandler-extras-8.5.0.jar 这两个 jar 包在 E:\config\solr\solr-8.5.0\dist 文件夹中存在
10.使用Springboot + solr实现增删改查
配置 pom.xml 文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
配置yml文件
spring:
data:
solr:
host: http://localhost:8983/solr # spring data框架定义的访问地址,不能提供索引库定义,是直接连接数据源的,可以根据索引库命名访问任意索引库,实现数据访问的。
# solr集群
# zk-host: http://xxx,http://xxx
Entity文件
import lombok.Data;
import org.apache.solr.client.solrj.beans.Field;
import org.springframework.data.annotation.Id;
import org.springframework.data.solr.core.mapping.SolrDocument;
/**
* spring data for apache solr 识别实体的时候,属性名和字段名一一对应
* SolrDocument注解:当前实体对应一个 solr 的索引库
*/
@Data
@SolrDocument(collection = "my_solr_core")
public class SolrInventoryEntity {
@Id
@Field
private String id;
@Field
private String drugname;
@Field
private String dosage;
@Field
private String packingunit;
@Field
private String specification;
@Field
private String barcode;
@Field
private String approvalnum;
@Field
private String attending;
@Field
private String drugbrand;
@Field
private String registeraddress;
@Field
private String manufacturers;
}
Controller文件
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ys.medical.page.PageResultDto;
import com.ys.medical.page.ResponseEntity;
import com.ys.medical.warehouse.dto.SolrInventoryDto;
import com.ys.medical.warehouse.entity.SolrInventoryEntity;
import com.ys.medical.warehouse.service.SolrService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/solr")
@Api(value = "solr搜索引擎", tags = {"solr搜索引擎"})
public class SolrController {
@Resource
private SolrService solrService;
/**
* 新增或更新(id相同为更新)
* @param solrInventoryEntity 新增或修改的对象数据
*/
@PostMapping("/updatesolr")
@ApiOperation("新增或更新(id相同为更新)")
public ResponseEntity<String> updateSolr(SolrInventoryEntity solrInventoryEntity){
solrService.updateSolr(solrInventoryEntity);
return ResponseEntity.success();
}
/**
* 批量新增或更新(id相同为更新)
* @param solrInventoryEntitys 新增或修改的对象数据
*/
@PostMapping("/updatesolrs")
@ApiOperation("批量新增或更新(id相同为更新)")
public ResponseEntity<String> updateSolrs(List<SolrInventoryEntity> solrInventoryEntitys){
solrService.updateSolrs(solrInventoryEntitys);
return ResponseEntity.success();
}
/**
* 删除
* @param ids 主键集合
*/
@PostMapping("/delete")
@ApiOperation("通过主键删除")
public ResponseEntity<String> delete(@RequestBody List<String> ids) {
solrService.delete(ids);
return ResponseEntity.success();
}
/**
* 通过名称查询列表
* @param pageIndex 页面(首页从 0 开始)
* @param pageSize 每页显示条数
* @param drugname 关键字
*/
@GetMapping("/querylist")
@ApiOperation("通过名称查询列表")
public ResponseEntity<PageResultDto<SolrInventoryEntity>> queryList(@RequestParam(defaultValue = "1") Integer pageIndex,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam String drugname){
IPage<SolrInventoryEntity> list = solrService.queryList(pageIndex, pageSize, drugname);
return ResponseEntity.success(new PageResultDto<>(list));
}
/**
* 通过名称查询列表(高亮)
* @param pageIndex 页面(首页从 0 开始)
* @param pageSize 每页显示条数
* @param drugname 关键字
*/
@GetMapping("/queryhighlightlist")
@ApiOperation("通过名称查询列表(高亮)")
public ResponseEntity<PageResultDto<SolrInventoryDto>> queryHighlightList(@RequestParam(defaultValue = "1") Integer pageIndex,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam String drugname){
IPage<SolrInventoryDto> list = solrService.queryHighlightList(pageIndex, pageSize, drugname);
return ResponseEntity.success(new PageResultDto<>(list));
}
}
Service文件
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ys.medical.warehouse.dto.SolrInventoryDto;
import com.ys.medical.warehouse.entity.SolrInventoryEntity;
import java.util.List;
public interface SolrService {
void updateSolr(SolrInventoryEntity solrInventoryEntity);
void updateSolrs(List<SolrInventoryEntity> solrInventoryEntitys);
void delete(List<String> ids);
IPage<SolrInventoryEntity> queryList(Integer pageIndex, Integer pageSize, String drugname);
IPage<SolrInventoryDto> queryHighlightList(Integer pageIndex, Integer pageSize, String drugname);
}
ServiceImpl文件
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.medical.warehouse.dto.SolrInventoryDto;
import com.ys.medical.warehouse.entity.SolrInventoryEntity;
import com.ys.medical.warehouse.service.SolrService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.*;
import org.springframework.data.solr.core.query.result.HighlightEntry;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.data.solr.core.query.result.ScoredPage;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service("solrService")
public class SolrServiceImpl implements SolrService {
@Resource
private SolrTemplate solrTemplate;
// solr 中定义的索引库名称
private final String INDEX_LIBRARY_NAME="my_solr_core";
@Override
public void updateSolr(SolrInventoryEntity solrInventoryEntity) {
solrTemplate.saveBean(INDEX_LIBRARY_NAME, solrInventoryEntity);
solrTemplate.commit(INDEX_LIBRARY_NAME);
}
@Override
public void updateSolrs(List<SolrInventoryEntity> solrInventoryEntitys) {
solrTemplate.saveBeans(INDEX_LIBRARY_NAME, solrInventoryEntitys);
solrTemplate.commit(INDEX_LIBRARY_NAME);
}
@Override
public void delete(List<String> ids) {
solrTemplate.deleteByIds(INDEX_LIBRARY_NAME, ids);
solrTemplate.commit(INDEX_LIBRARY_NAME);
}
@Override
public IPage<SolrInventoryEntity> queryList(Integer pageIndex, Integer pageSize, String drugname) {
// 通用条件模板
Criteria criteria = Criteria.where("drugname").is(drugname);
// 查询条件对象
Query query = Query.query(criteria);
// 通过主键倒序排序
query.addSort(Sort.by(Sort.Direction.DESC, "id"));
// 分页(页面从 0 开始)
query.setPageRequest(PageRequest.of(pageIndex-1, pageSize));
// query.setPageRequest(PageRequest.of(pageIndex, pageSize, Sort.by(Sort.Direction.DESC, "id")));
ScoredPage<SolrInventoryEntity> pageList = solrTemplate.queryForPage(INDEX_LIBRARY_NAME, query, SolrInventoryEntity.class);
List<SolrInventoryEntity> result = pageList.getContent(); // 分页数据
long totalElements = pageList.getTotalElements(); // 总条数
IPage<SolrInventoryEntity> page = new Page<>(pageIndex, pageSize);
page.setTotal(totalElements);
page.setRecords(result);
return page;
}
@Override
public IPage<SolrInventoryDto> queryHighlightList(Integer pageIndex, Integer pageSize, String drugname) {
HighlightQuery query = new SimpleHighlightQuery();
query.addCriteria(Criteria.where("drugname").is(drugname));
query.setPageRequest(PageRequest.of(pageIndex-1, pageSize, Sort.by(Sort.Direction.DESC, "id")));
HighlightOptions options = new HighlightOptions();
options.addField("drugname");
options.setSimplePrefix("<span style='color:red'>");
options.setSimplePostfix("</span>");
query.setHighlightOptions(options);
HighlightPage<SolrInventoryEntity> pageList =
solrTemplate.queryForHighlightPage(INDEX_LIBRARY_NAME, query, SolrInventoryEntity.class);
// 分页数据,不包括高亮
List<SolrInventoryEntity> result = pageList.getContent();
List<SolrInventoryDto> dtoList = Optional.ofNullable(result).orElse(new ArrayList<>()).stream().map(item->{
SolrInventoryDto dto = new SolrInventoryDto();
BeanUtils.copyProperties(item, dto);
// 根据当前 POJO 对象,查询高亮数据
List<HighlightEntry.Highlight> highlights = pageList.getHighlights(item);
dto.setHighlights(highlights);
return dto;
}).collect(Collectors.toList());
long totalElements = pageList.getTotalElements(); // 总条数
IPage<SolrInventoryDto> page = new Page<>(pageIndex, pageSize);
page.setTotal(totalElements);
page.setRecords(dtoList);
return page;
}
}