本文转自本人博客:https://funyan.cn/p/6364.html
前言
类似于百度等搜索引擎,我们的搜索词都会在搜索结果中显示红色或其他高亮颜色,这就叫高亮显示,ElasticSearch同样也是支持这个功能的,下面我们就看一下如何用es实现搜索结果的高亮显示
教程
1、重写高亮显示的mapper类
package cn.funyan.blog.es;
import com.alibaba.fastjson.JSONObject;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.bytes.ByteBufferReference;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.DefaultResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import java.nio.ByteBuffer;
import java.util.Map;
/**
*高亮显示类
**/
public class HighlightResultMapper extends DefaultResultMapper
{
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
for (SearchHit hit : response.getHits()) {
Map<String, Object> sourceMap = hit.getSourceAsMap();
for (Map.Entry<String, HighlightField> entry : hit.getHighlightFields().entrySet()) {
String key = entry.getKey();
if (sourceMap.containsKey(key)) {
Text[] fragments = entry.getValue().getFragments();
sourceMap.put(key, transTextArrayToString(fragments));
}
}
hit.sourceRef(new ByteBufferReference(ByteBuffer.wrap(JSONObject.toJSONString(sourceMap).getBytes())));
}
return super.mapResults(response, clazz, pageable);
}
private String transTextArrayToString(Text[] fragments) {
if (null == fragments) {
return "";
}
StringBuffer buffer = new StringBuffer();
for (Text fragment : fragments) {
buffer.append(fragment.string());
}
return buffer.toString();
}
}
2、编写搜索方法
public List<Article> searchArtV2(Integer pageNum, String keywords) {
if(StringUtils.isEmpty(keywords)){
return new Res().failed().setMsg("搜索词不得为空");
}
//构建分页数据
Pageable pageable=PageRequest.of(Page.getEsPageNum(pageNum),Page.DEFAULT_PAGESIZE);
//构建条件查询器
QueryStringQueryBuilder boolQueryBuilder = new QueryStringQueryBuilder(keywords);
//构建条件
boolQueryBuilder.field("head")
.field("introduce");
//构建查询器
//高亮的前缀和后缀,这里可以自定义,只要可以高亮显示
String preTag = "<em>";
String postTag = "</em>";
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withFields("id","head","titlePhoto","pageView","createdAt","description","introduce","classifyName")
//重点!!!这里支持检索的字段高亮,显示高亮的必须是你检索的字段
.withHighlightFields(new HighlightBuilder.Field("head").preTags(preTag).postTags(postTag),new HighlightBuilder.Field("introduce").preTags(preTag).postTags(postTag))
.withPageable(pageable)
.build();
//这里直接传入我们写的高亮类
AggregatedPage<Article> articles = elasticsearchRestTemplate.queryForPage(searchQuery, Article.class, new HighlightResultMapper());
List<Article> list=articles.getContent();
log.info("用户搜索文章:{}",JSONObject.toJSON(result));
return list;
}
3、这样就可以看到我们的搜索词都加上了<em></em>标签,效果如下
本文转自本人博客:https://funyan.cn/p/6364.html