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
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
yml
spring:
elasticsearch:
uris: xxx
username: xxxx
password: xxxxx
3. 代码实现
java
@Data
@Document(indexName = "user")
public class User {
@Id
private 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;
}
java
@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. 结束语
本文通过一些非常规手段实现对应的高亮分页查询;仅供参考,如有更好的方式请留言指导,谢谢各位。