文章目录
- 1. 前情配置
- 2、数据操作
- 2.1 操作API
- 2.2 数据入库
- 3. 高亮搜索
- 3.1 方法封装
- 3.2 高亮搜索
1. 前情配置
为满足ElasticSearch
可在项目中实现搜索高亮,我们需要先做一些前情配置
- 导入
ElasticSearch
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
- 修改
propertise
配置
server.port=9090
spring.thymeleaf.cache=false
# 保证url可以输入中文,防止乱码
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
- 构建一个搜索类对象,这里假设我们存在一个搜索对象为
Content
,其中我们要进行查询的字段是title
@AllArgsConstructor
@NoArgsConstructor
@Data
@Component
public class Content {
private String title;
private String img;
private String price;
}
同时,假设我们拥有List<Content>
数据集合,至此,我们做好了所有的前情准备
2、数据操作
2.1 操作API
我们拥有List<Content>
数据集合,我们要将其插入到es
中
步骤分为三步:判断索引是否存在 -> 索引不存在则创建索引 -> 索引存在则插入文档
则数据操作的API
分为三个,我们一一实现
API(1):判断索引是否存在
public boolean existIndex(String indexName) throws IOException {
GetIndexRequest request = new GetIndexRequest(indexName);
boolean isExists = client.indices().exists(request, RequestOptions.DEFAULT);
return isExists;
}
API(2):创建索引
这里的indexName
利用jd_goods
传入,即我们创建的索引名称为jd_goods
public boolean createIndex(String indexName) throws IOException {
CreateIndexRequest request = new CreateIndexRequest(indexName);
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
return response.isAcknowledged();
}
API(3):批量插入数据
这里的indexName
利用jd_goods
传入,即我们将的List<Content>
数据插入到jd_goods
public boolean bulkAddDoc(String indexName, List<Content> listContent) throws IOException {
//判断是否存在索引
if (indexService.existIndex()){
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
//存入数据
for (Content content : listContent) {
bulkRequest.add(new IndexRequest(indexName)
.source(JSON.toJSONString(content), XContentType.JSON));
}
//执行请求
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
//不失败表示插入成功
return !bulkResponse.hasFailures();
}
return false;
}
2.2 数据入库
整合上述方法,我们可以将List<Content>
存入es
中
public boolean parseContent(String indexName,List<Content> list) throws IOException {
//1. 某个获取数据的方法
List<Content> list = function();
//2. 判断索引是否存在,并且插入数据
if (!indexService.existIndex(String indexName)){
indexService.createIndex(String indexName);
}
//3. 插入数据
return docService.bulkAddDoc(String indexName,list);
}
再次查看es
,数据已经被插入
3. 高亮搜索
3.1 方法封装
封装用于搜索的方法,这里指定利用term
搜索
//param搜索字段名称 searchWord搜索关键字,from和size用于分页
public List<Map<String, Object>> searchDoc(String indexName, String param, String searchWord, Integer from, Integer size) throws IOException {
//构建搜索类
SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
//匹配查询
TermQueryBuilder termQuery = QueryBuilders.termQuery(param, searchWord);
//设置超时
searchBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
//设置高亮的字段
highlightBuilder.field(param);
//多个高亮显示
highlightBuilder.requireFieldMatch(false);
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
searchBuilder.highlighter(highlightBuilder);
//分页
if (from <= 0){
from = 0;
}
if (size != 0){
searchBuilder.from(from);
searchBuilder.size(size);
}
//封装搜索
searchBuilder.query(termQuery);
//创建查询请求,并将搜索类放入
SearchRequest request = new SearchRequest(indexName).source(searchBuilder);
//客户端查询请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//解析结果,第一次getHits()返回了全部的数据,包括版本信息等
//第二次getHits()返回了数据中的查询对象
//getSourceAsMap()表示将查询对象转化为map集合,其中键就是属性,值就是属性对应的值
ArrayList<Map<String, Object>> list = new ArrayList<>();
for(SearchHit hit:response.getHits().getHits()){
//使用新的高亮字段,覆盖旧字段
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//获取全部的高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField title = highlightFields.get(param);
//开始替换,将旧的title值替换为高亮的值
if (title != null){
Text[] fragments = title.getFragments();
StringBuilder newTitle = new StringBuilder();
for (Text text:fragments){
newTitle.append(text);
}
sourceAsMap.put(param,newTitle);
}
//再次添加进去
list.add(sourceAsMap);
}
return list;
}
整合上述方法,假设我们在jd_goods
中搜索title
字段
public List<Map<String, Object>> searchContent(String indexName, String keyword,Integer from,Integer size) throws IOException {
return docService.searchDoc("jd_goods","title",keyword,from,size);
}
3.2 高亮搜索
绑定浏览器地址,尝试查询
@GetMapping("/search/{keyword}/{from}/{size}")
public List<Map<String, Object>> searchContent(@PathVariable("keyword") String keyword,
@PathVariable("from") Integer from,@PathVariable("size") Integer size) throws IOException {
return contentService.searchContent(keyword,from,size);
}
假设我们需要搜索jd_goods
中搜索title
字段包含java
的字段,同时从第1条数据开始获取,获取的数据大小为20
访问浏览器,关键字已经被设置高亮,只需要传递到前端即可