文章目录
- 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
访问浏览器,关键字已经被设置高亮,只需要传递到前端即可