前言
前面我们已经对spring 和 elasticsearch做了整合,这里便在前面的基础上使用es数据完成我们的项目列表及一系列查询分页排序及高亮等功能
引入
先看一下使用es数据完成列表及分页高亮等的效果图
ElasticsearchTemplate
- ElasticsearchTemplate 封装ES客户端的一些原生api模板,方便实现一些查询
elasticsearchTemplate.queryForPage #是查询一个分页列表,用的就是一个对象实例
NativeSearchQuery #是springdata中的查询条件
NativeSearchQueryBuilder #用于建造一个NativeSearchQuery查询对象
QueryBuilders #设置查询条件,是ES中的类
SortBuilders #设置排序条件
HighlightBuilder #设置高亮显示
QueryBuilders
- QueryBuilders是ES中的查询条件构造器
QueryBuilders.boolQuery #子方法must可多条件联查
QueryBuilders.termQuery #精确查询指定字段
QueryBuilders.matchQuery #按分词器进行模糊查询
QueryBuilders.rangeQuery #按指定字段进行区间范围查询
# 大于等于 .from .gte
# 小于等于 .to .lte
NativeSearchQuery
- 原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询,最终进行构建.build 可作为ElasticsearchTemplate. queryForPage的参数使用
//构建Search对象
NativeSearchQuery build = new NativeSearchQueryBuilder()
//条件
.withQuery(queryBuilder)
//排序
.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
//高亮
.withHighlightFields(name, ms)
//分页
.withPageable(PageRequest.of(pageNum - 1, pageSize))
//构建
.build();
AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());
//queryForPage 参数一: NativeSearchQuery 封装的查询数据对象
参数二: es对应索引实体类
参数三: 调用高亮工具类
总体查询数据至列表页面代码,每一步均有解释
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@RequestMapping(value = "list")
public String list(@ModelAttribute(value = "vo") QueryVo vo, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize, Model model){
//高亮显示
String pre = "<span style='color:red'>";
String post = "</span>";
//指定要高亮的字段将其加上头尾标签
HighlightBuilder.Field name = new HighlightBuilder.Field("name").preTags(pre).postTags(post);
HighlightBuilder.Field ms = new HighlightBuilder.Field("ms").preTags(pre).postTags(post);
//查询高亮结果不分片,不加此条会按分词器高亮显示(数据变少)
ms.numOfFragments(1);
//多查询条件 must 可不断添加条件
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
if(StringUtils.isNoneBlank(vo.getName())){
//精确查询
queryBuilder.must(QueryBuilders.termQuery("name.keyword",vo.getName()));
}
if(StringUtils.isNoneBlank(vo.getMs())){
//模糊查询
queryBuilder.must(QueryBuilders.matchQuery("ms",vo.getMs()));
}
//根据指定字段区间查询 from(gte) 大于等于 to(lte) 小于等于
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
if(vo.getStartpice() != null){
rangeQuery.from(vo.getStartpice());
}
if(vo.getEndpice() != null){
rangeQuery.to(vo.getEndpice());
}
queryBuilder.must(rangeQuery);
//构建Search对象
NativeSearchQuery build = new NativeSearchQueryBuilder()
//条件
.withQuery(queryBuilder)
//排序
.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
//高亮
.withHighlightFields(name, ms)
//分页
.withPageable(PageRequest.of(pageNum - 1, pageSize))
//构建
.build();
AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());
//封装分页数据至list集合中
Page<Goods> page = new Page<>(pageNum, pageSize);
//填充分页总条数
page.setTotal(aggregatedPage.getTotalElements());
//封装至pageinfo内,实现列表
PageInfo<Goods> pg = new PageInfo<>(page);
//将es查询到当前页的数据 封装至pg中
pg.setList(aggregatedPage.getContent());
//传入前端,实现列表页面
model.addAttribute("pg",pg);
return "list";
}
认真看的伙伴可以看出上方我引入了高亮工具类,下面对高亮工具类进行详解(亮点)
es高亮工具类(可直接复制,亲测有效)
public class Hig implements SearchResultMapper { /* searchResponse 封装高亮查询结果集 clazz 要封装的es索引对应实体类对象 pageable */ @Override public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> clazz, Pageable pageable) { //获取es搜索数据集合对象 SearchHits hits = searchResponse.getHits(); //获取高亮搜索后数据的总条数 long totalHits = hits.getTotalHits(); //搭建存储数据集合对象 ArrayList<T> list = new ArrayList<>(); //判断高亮结果有数据 if(hits.getHits().length > 0){ //遍历数据集合 for (SearchHit searchHit : hits) { //获取结果集中所有要高亮字段 final Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); //把json串转为目标对象 T t = JSON.parseObject(searchHit.getSourceAsString(), clazz); //获取目标对象的所有属性 Field[] fields = clazz.getDeclaredFields(); //遍历属性 for (Field field : fields) { //打破私有封装 field.setAccessible(true); 如果高亮的字段和要封装的对象的名字一致则值要重新封装 if(highlightFields.containsKey(field.getName())){ try { //将查询到的数据进行高亮替换 field.set(t,highlightFields.get(field.getName()).fragments()[0].toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } } } //存入数据集合中 list.add(t); } } //返回数据集合,排序对象,集高亮总条数 return new AggregatedPageImpl<>(list,pageable,totalHits); } }
解释下高亮是什么? 就是你百度时根据你搜索到的关键字高亮显示的特殊字体,例:下图
Thanks!