springboot2.2.x对接elasticsearch7.2.0,实现分页搜索情况下的高亮和摘要功能
<spring.boot.version>2.2.0.RELEASE</spring-boot.version>
<!-- elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
spring:
elasticsearch:
rest:
#es地址
uris: http://192.168.125.12:9200
@Service
public class EsPageService {
/**
* spring-boot-starter-data-elasticsearch会自动注入,可直接使用
**/
@Autowired
private RestHighLevelClient esClient;
public PageInfo<Asset> searchPageWithHighlight(EsPageQuery esPageQuery) {
SearchRequest searchRequest = new SearchRequest("asset");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//构造多条件查询
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 添加基本的分词条件
if (StringUtils.isNotBlank(esPageQuery.getJsonValue())) {
boolQueryBuilder.must(matchQuery("jsonStr", esPageQuery.getJsonValue()));
}
//精确匹配
if (null != esPageQuery.getType()) {
boolQueryBuilder.must(termQuery("assetType", esPageQuery.getType()));
}
//数据过滤
if (esPageQuery.getStartTime() != null && esPageQuery.getEndTime() != null &&
esPageQuery.getEndTime().compareTo(esPageQuery.getStartTime()) >= 0) {
boolQueryBuilder.filter(rangeQuery("createTime").
gte(esPageQuery.getStartTime().getTime()).lte(esPageQuery.getEndTime().getTime()));
}
sourceBuilder.query(boolQueryBuilder);
// 排序条件
if (StringUtils.isNotBlank(esPageQuery.getProperty())) {
sourceBuilder.sort(SortBuilders.fieldSort(esPageQuery.getProperty()).order(SortOrder.DESC));
}
//分页
sourceBuilder.from(esPageQuery.getCurrent() - 1);
sourceBuilder.size(esPageQuery.getSize());
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("jsonStr");
//设置高亮片段
highlightBuilder.fragmentSize(100);
highlightBuilder.numOfFragments(1);
highlightBuilder.noMatchSize(0);
//多个高亮显示设置为true
highlightBuilder.requireFieldMatch(false);
highlightBuilder.preTags("<em style='color:red;font-style: normal;'>");
highlightBuilder.postTags("</em>");
sourceBuilder.highlighter(highlightBuilder);
//执行搜索
searchRequest.source(sourceBuilder);
SearchResponse search;
try {
search = esClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException ex) {
throw new BizException("es查询失败");
}
//解析结果
EsPage pageInfo = new EsPage();
pageInfo.setList(new ArrayList());
for (SearchHit hit : search.getHits().getHits()) {
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField title = highlightFields.get("jsonStr");
//原来的结果
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//解析高亮字段 ,将原来的字段换成高亮字段显示
if (title != null) {
Text[] fragments = title.fragments();
String newTitle = "";
for (Text fragment : fragments) {
newTitle += fragment;
}
//增加高亮字段
sourceAsMap.put("summary", newTitle);
}
Asset asset = BeanUtil.mapToBean(hit.getSourceAsMap(), Asset.class, CopyOptions.create());
pageInfo.getList().add(asset);
}
pageInfo.setTotal(search.getHits().totalHits);
pageInfo.setPageNum(esPageQuery.getCurrent());
pageInfo.setSize(esPageQuery.getSize());
//聚合信息
NativeSearchQueryBuilder aggregationQueryBuilder = new NativeSearchQueryBuilder();
aggregationQueryBuilder.addAggregation(AggregationBuilders.terms("assetTypeCount").field("assetType"));
AggregatedPage<Asset> aggregationsSearch = (AggregatedPage<Asset>) assetRepository.search(aggregationQueryBuilder.build());
Aggregation aggregation = aggregationsSearch.getAggregation("assetTypeCount");
pageInfo.setTypeCount(new ArrayList<>());
((ParsedLongTerms) aggregation).getBuckets().stream().forEach(s -> {
pageInfo.getTypeCount().add(new EsPage.AssetCount()
.setType(Integer.valueOf(s.getKeyAsString())).setCount(s.getDocCount()));
});
return pageInfo;
}
}