1. 前言
项目基础为springboot3.0.2,目标是实现Elasticsearch的自定义高亮分页查询,网上提供的方法都是通过继承ElasticsearchRepository实现相关的查询,但是当我查询条件过多且复杂的时候方法命名会非常长,所以暂时弃用,投奔之前用过的spring-boot-starter-data-elasticsearch(主要使用的还是spring-data-elasticsearch5.0.1)。
由于spring-data-elasticsearch5.0.1版本中弃用了ElasticsearchRestTemplate类以及HighlightBuilder,高亮查询就变得异常麻烦。
2. 依赖与参数配置
2.1 pom.xml
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><version>3.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser -->
<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>8.11.2</version>
</dependency>
2.2 application.yml
spring:elasticsearch:uris: xxxusername: xxxxpassword: xxxxx
3. 代码实现
@Data
@Document(indexName = "user")
public class User {@Idprivate String id;@Field(type = FieldType.Text, analyzer = "ik_max_word")private String name;@Field(type = FieldType.Date)private Date bir;@Field(type = FieldType.Text,analyzer = "ik_max_word")private String content;
}
@Service
@RequiredArgsConstructor
public class EsService {private final ElasticsearchTemplate restTemplate;/*** 初始化es序列*/public boolean initIndex() {IndexOperations indexOperations = restTemplate.indexOps(User.class);if (!indexOperations.exists()) {indexOperations.create();Document mapping = indexOperations.createMapping();indexOperations.putMapping(mapping);return true;}return false;}/*** 初始化es数据** @throws IOException*/public void initEsData() {// 查询获取用户信息restTemplate.save(users);}/*** 分页查询数据** @param keyword* @param pageNo* @param pageSize* @throws IOException*/@Highlight(fields = {@HighlightField(name = "field1"),@.HighlightField(name = "field12"),@HighlightField(name = "field13")},parameters = @HighlightParameters(preTags = "<span style='color:#799ed9'>",postTags = "</span>",fragmentSize = 30,numberOfFragments = 3,requireFieldMatch = false))// 高亮配置信息public PageInfo<User> searchEs(String keyword, Integer pageNo, Integer pageSize) {PageInfo<User> pageInfo = new PageInfo<>();if (pageNo <= 0) {pageNo = 1;}if (pageSize <= 0) {pageSize = 10;}pageInfo.setPageNo(pageNo);pageInfo.setPageSize(pageSize);// 分页数据Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.Direction.DESC, "publishDate");// 条件查询SimpleQueryStringQuery queryBuilder = null;if (StringUtils.isNotBlank(keyword)) {keyword = QueryParser.escape(keyword);keyword = "\"" + keyword + "\"";queryBuilder = new SimpleQueryStringQuery.Builder().fields("field1", "field2").query(keyword).analyzer("ik_max_word").build(); // 查询条件}SimpleQueryStringQuery finalQueryBuilder = queryBuilder;NativeQueryBuilder builder = NativeQuery.builder();if (queryBuilder != null) {builder = builder.withQuery(q -> q.simpleQueryString(finalQueryBuilder));}// 创建一个HighlightQuery实例,指定要高亮的字段Method method = getMethod(EsService.class, "searchEs");if (method != null) {Highlight highlight = method.getAnnotation(Highlight.class);HighlightQuery highlightQuery = new HighlightQuery(org.springframework.data.elasticsearch.core.query.highlight.Highlight.of(highlight),User.class);builder = builder.withHighlightQuery(highlightQuery);}Query query = builder.withPageable(pageable).build();SearchHits<User> search = restTemplate.search(query, User.class);List<SearchHit<User>> searchHits = search.getSearchHits();long totalHits = search.getTotalHits();if (totalHits <= 0) {return pageInfo;}pageInfo.setCount(totalHits);List<User> list = new ArrayList<>();// 设置高亮数据for (SearchHit<User> hit : searchHits) {User content = hit.getContent();JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(content));Map<String, List<String>> highlightFields = hit.getHighlightFields();if (highlightFields.isEmpty()) {list.add(content);continue;}for (Map.Entry<String, List<String>> entry : highlightFields.entrySet()) {StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i < entry.getValue().size(); i++) {if (i > 0) {stringBuffer.append(",");}stringBuffer.append(entry.getValue().get(i));}jsonObject.put(entry.getKey(), stringBuffer.toString());}content = JSONObject.parseObject(jsonObject.toJSONString(), User.class);list.add(content);}pageInfo.setList(list);return pageInfo;}/*** 获取方法** @param clz* @param methodName* @return*/private Method getMethod(Class clz, String methodName) {Method[] methods = clz.getMethods();for (Method method : methods) {if (!method.getName().equals(methodName)) {continue;}return method;}return null;}
}
4. 结束语
本文通过一些非常规手段实现对应的高亮分页查询;仅供参考,如有更好的方式请留言指导,谢谢各位。