Elasticsearch java高亮显示
Elasticsearch java高亮显示
- 为什么要写
- 因为版本原因很多网上的案例变动较大
- 基于springboot 2.2.2 elasticsearch 7.10.1
原理
-
elastic支持,请求格式如下:
{ "query": { "bool": { "should": [ { "match": { "addName": "test" } }, { "match": { "fileName": "环境" } } ], "minimum_should_match": 2 } }, "highlight": { "fields": { "fileName":{} } } }
基于API的实现
-
网上找到的常用版本
public Object queryKeyWord(HttpServletRequest request, @RequestParam(value = "keyWord")String keyWord, @RequestParam(value = "page")int page, @RequestParam(value = "size")int size) throws IOException { // 在索引中进行查询 SearchRequest searchRequest = new SearchRequest(esDocumentIndex); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 搜索名字 TermQueryBuilder termQuery = QueryBuilders.termQuery("fileName", keyWord); sourceBuilder.query(termQuery); sourceBuilder.from(page); sourceBuilder.size(size); // sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 添加高亮 HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field highlightName = new HighlightBuilder.Field("fileName"); //把 fileName 域设为高亮 highlightBuilder.field(highlightName); highlightBuilder.preTags(""); highlightBuilder.postTags(""); sourceBuilder.highlighter(highlightBuilder); // 发起请求 searchRequest.source(sourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); // 保存高亮 ArrayList -
方法二
实现DocumentRepository
public interface DocumentRepository extends ElasticsearchRepository{ } 构建查询
// 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.matchQuery("fileName", keyWord)); // 添加高亮 HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field highlightName = new HighlightBuilder.Field("fileName"); //把 name 域设为高亮 highlightBuilder.field(highlightName); highlightBuilder.preTags(""); highlightBuilder.postTags(""); queryBuilder.withHighlightBuilder(highlightBuilder); queryBuilder.withPageable(PageRequest.of(page, size)); // 搜索,获取结果 Pageitems = documentRepository.search(queryBuilder.build()); 发现高亮没有生效,跟踪源码发现在箭头区域给过滤掉了
解决办法
自己重写这个方法,查看结构自己定义一个mapper转换,返回就行。
但是查看search方法没有接收参数
@NoRepositoryBean public interface ElasticsearchRepositoryextends ElasticsearchCrudRepository { S index(S entity); /** * This method is intended to be used when many single inserts must be made that cannot be aggregated to be inserted * with {@link #saveAll(Iterable)}. This might lead to a temporary inconsistent state until {@link #refresh()} is * called. */S indexWithoutRefresh(S entity); Iterablesearch(QueryBuilder query); Page search(QueryBuilder query, Pageable pageable); Page search(SearchQuery searchQuery); Page searchSimilar(T entity, String[] fields, Pageable pageable); void refresh(); Class getEntityClass(); } 继续向下找,发现search调用的是queryForPage
@Override public Pagesearch(SearchQuery query) { return elasticsearchOperations.queryForPage(query, getEntityClass()); } 继续找发现在下一步参数中多了一个resultsMapper,而出问题的方法也在这个参数对象中,于是我们只需要重写这个参数并调用这个方法就可以了。
@Override publicAggregatedPage queryForPage(SearchQuery query, Class clazz) { return queryForPage(query, clazz, resultsMapper); } 重写参数
public class HighlightResultMapper implements SearchResultMapper { @Override publicAggregatedPage mapResults(SearchResponse searchResponse, Class clazz, Pageable pageable) { long totalHits = searchResponse.getHits().getTotalHits(); List list = new ArrayList<>(); SearchHits hits = searchResponse.getHits(); if (hits.getHits().length> 0) { for (SearchHit searchHit : hits) { Map highlightFields = searchHit.getHighlightFields(); T item = JSON.parseObject(searchHit.getSourceAsString(), clazz); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); if (highlightFields.containsKey(field.getName())) { try { field.set(item, highlightFields.get(field.getName()).fragments()[0].toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } } } list.add(item); } } return new AggregatedPageImpl<>(list, pageable, totalHits); } @Override public T mapSearchHit(SearchHit searchHit, Class type) { return null; } } 更改调用过程
// 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本分词查询 queryBuilder.withQuery(QueryBuilders.matchQuery("fileName", keyWord)); // 添加高亮 HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field highlightName = new HighlightBuilder.Field("fileName"); //把 name 域设为高亮 highlightBuilder.field(highlightName); highlightBuilder.preTags(""); highlightBuilder.postTags(""); queryBuilder.withHighlightBuilder(highlightBuilder); queryBuilder.withPageable(PageRequest.of(page, size)); // 搜索,获取结果 // Pageitems = documentRepository.search(queryBuilder.build()); SearchQuery searchQuery = null; searchQuery= queryBuilder.build(); Page items = new ElasticsearchRestTemplate(restHighLevelClient).queryForPage(searchQuery,DocumentPo.class,new HighlightResultMapper());
完!