ElasticSearch查询高亮显示
ElasticSearch查询高亮显示
cmyang1. 需求背景
在使用ES进行搜索时,总需要在查询出来的内容中,把我们的搜索关键字高亮显示出来
2. 实现思路
3. 代码实现
引入maven依赖
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>自定义SearchResultMapper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54package com.xxx.web.cloud.bot.es.config;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author iseven.yang
* @date 2023/7/11 19:55
*/
public class HighlightResultMapper implements SearchResultMapper {
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long totalHits = response.getHits().getTotalHits();
List<T> list = new ArrayList<>();
SearchHits hits = response.getHits();
if (hits.getHits().length> 0) {
for (SearchHit searchHit : hits) {
Map<String, HighlightField> 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);
}
public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return null;
}
}检索高亮查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public List<AnswerButtonVO> searchQuestion(String searchKey) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 匹配问题的关键字、
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(QuestionDOC.QUESTION, searchKey);
boolQueryBuilder.must(matchQueryBuilder);
// 分页数据
PageRequest pageRequest = PageRequest.of(0, 5);
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder()
.field(QuestionDOC.QUESTION)
.preTags(CustomConstant.HIGHLIGHT_PREFIX) //String HIGHLIGHT_PREFIX = "<span class=\"highlight\">";
.postTags(CustomConstant.HIGHLIGHT_SUFFIX); //String HIGHLIGHT_SUFFIX = "</span>";
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withPageable(pageRequest)
.withHighlightBuilder(highlightBuilder)
.build();
AggregatedPage<QuestionDOC> searchPage = elasticsearchRestTemplate.queryForPage(nativeSearchQuery, QuestionDOC.class, new HighlightResultMapper());
List<QuestionDOC> content = searchPage.getContent();
...
}