<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
/**
* es搜索引擎参数
*
* @author xzx
* @date 2022/10/4
*/
@Data
@Accessors(chain = true)
public class SearchReqDto {
/**
* 当前页码
*/
private Integer pageNum = 1;
/**
* 页数
*/
private Integer pageSize = 10;
/**
* 索引库名称
*/
private String indices;
/**
* 关键词
*/
private String keyword;
/**
* 排序字段
*/
private String orderByColumn = "createdTime";
/**
* asc or desc
*/
private String isAsc = "asc";
/**
* 高亮字段
*/
private String[] highlightFields;
}
分页、高亮、排序
/**
* elasticsearch配置类
*
* @author xzx
* @date 2022/10/2
*/
@Configuration
public class ESConfig {
@Value("${elasticsearch.url}")
private String elasticsearchUrl;
@Bean(name = "RestHighLevelClient")
public RestHighLevelClient restHighLevelClient() {
return new RestHighLevelClient(RestClient.builder(
HttpHost.create(elasticsearchUrl)
)
);
}
}
import java.io.IOException;
/**
* elasticsearch 封装类
*
* @author xzx
* @date 2022/10/4
*/
@Component
public class EsClient {
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 搜索并完成分页、高亮、排序
*
* @param req
* @param beanClass
* @return responseResult
* @throws IOException
*/
public <T> ResponseResult findObject(SearchReqDto req, Class<T> beanClass) throws IOException {
if (ObjUtil.isNull(req) || StringUtil.isBlank(req.getIndices())) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
}
if (StringUtil.isBlank(req.getOrderByColumn())) {
req.setOrderByColumn("createdTime");
}
List<Object> resultList = null;
Map<Object, Object> resultMap = new HashMap<>();
SearchHits hits = queryBuilder(req);
T bean = null;
resultList = new ArrayList<>();
//遍历查询结果并接收
for (SearchHit searchHit : hits) {
/**
* 关键词为空或者没有高亮字段,不需要再处理
*/
if (StringUtil.isBlank(req.getKeyword()) || ArrayUtil.isEmpty(req.getHighlightFields())) {
bean = JSONUtil.toBean(searchHit.getSourceAsString(), beanClass);
} else {
bean = replaceAttr(searchHit, req.getHighlightFields(), beanClass);
}
if (ObjUtil.isNotNull(bean)) {
resultList.add(bean);
}
}
resultMap.put("total", resultList.size());
resultMap.put("record", resultList);
return ResponseResult.okResult(resultMap);
}
/**
* 构造查询条件,获取原生返回数据
*
* @param req 查询条件
* @return SearchHit
* @throws IOException
*/
public SearchHits queryBuilder(SearchReqDto req) throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
HighlightBuilder highlightBuilder = new HighlightBuilder();
int pageNum = req.getPageNum() > 0 ? req.getPageNum() : 1;
int pageSize = req.getPageSize() > 0 ? req.getPageSize() : 10;
//设置分页
builder.from((pageNum - 1) * pageSize);
builder.size(pageSize);
//设置高亮
highlightBuilder.field("*"); //所有的字段都高亮
highlightBuilder.requireFieldMatch(false);//如果要多个字段高亮,这项要为false
highlightBuilder.preTags("").postTags("")
.fragmentSize(800000)//下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等; 最大高亮分片数
.numOfFragments(0);//从第一个分片获取高亮片段
builder.highlighter(highlightBuilder);
//模糊查询
if (StringUtil.isBlank(req.getKeyword())) {
boolQueryBuilder.should(QueryBuilders.matchAllQuery());
} else {
boolQueryBuilder.should(QueryBuilders.matchQuery("all", req.getKeyword()));
}
//对查询结果进行排序
SortOrder order = SortOrder.ASC;
if (SortOrder.DESC.name().equalsIgnoreCase(req.getIsAsc())) {
order = SortOrder.DESC;
}
builder.query(boolQueryBuilder).sort(req.getOrderByColumn(), order);
SearchRequest searchRequest = new SearchRequest(req.getIndices());
searchRequest.source(builder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
return searchResponse.getHits();
}
/**
* 将高亮字段替换
*
* @param searchHit 查询结果
* @param attrs 字段名
* @return T
*/
private <T> T replaceAttr(SearchHit searchHit, String[] attrs, Class<T> beanClass) {
T bean = null;
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
for (String field : attrs) {
HighlightField hField = highlightFields.get(field);
if (hField != null) {
//替换高亮字段
Text[] fragments = hField.fragments();
StringBuilder text = new StringBuilder();
for (Text textGet : fragments) {
text.append(textGet);
}
//对象的值只能读一次,否则会被覆盖
if (ObjUtil.isNull(bean)) {
//转换数据类型
bean = JSONUtil.toBean(searchHit.getSourceAsString(), beanClass);
}
//设置对象的属性值
ReflectUtil.invokeSetter(bean, field, text.toString());
}
}
return bean;
}
}
反射工具类ReflectUtil是我自定义的,原理是反射,可以引入hutool的工具包,同样也可以实现该结果