package com.kidgrow.searchcenter.util;
|
|
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.BooleanUtil;
|
import cn.hutool.core.util.StrUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.kidgrow.common.model.PageResult;
|
import lombok.Data;
|
import lombok.Getter;
|
import lombok.Setter;
|
import org.apache.commons.beanutils.PropertyUtils;
|
import org.elasticsearch.action.search.SearchRequestBuilder;
|
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.common.text.Text;
|
import org.elasticsearch.index.query.QueryBuilder;
|
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.search.SearchHits;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
|
import org.elasticsearch.search.sort.SortOrder;
|
import org.springframework.data.elasticsearch.ElasticsearchException;
|
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
|
import java.lang.reflect.InvocationTargetException;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
import java.util.Map;
|
|
|
/**
|
* 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020<br>
|
*
|
* @Description: ES查询Builder<br>
|
* @Project: <br>
|
* @CreateDate: Created in 2020/2/24 12:13 <br>
|
* @Author: <a href="4345453@kidgrow.com">liuke</a>
|
*/
|
@Data
|
public class SearchBuilder {
|
/**
|
* 高亮前缀
|
*/
|
private static final String HIGHLIGHTER_PRE_TAGS = "<mark>";
|
/**
|
* 高亮后缀
|
*/
|
private static final String HIGHLIGHTER_POST_TAGS = "</mark>";
|
|
private SearchRequestBuilder searchBuilder;
|
|
private SearchBuilder(SearchRequestBuilder searchBuilder) {
|
this.searchBuilder = searchBuilder;
|
}
|
|
/**
|
* 生成SearchBuilder实例
|
* @param elasticsearchTemplate
|
* @param indexName
|
*/
|
public static SearchBuilder builder(ElasticsearchTemplate elasticsearchTemplate, String indexName) {
|
SearchRequestBuilder searchBuilder = elasticsearchTemplate.getClient().prepareSearch(indexName);
|
return new SearchBuilder(searchBuilder);
|
}
|
|
/**
|
* 生成queryStringQuery查询
|
* @param queryStr 查询关键字
|
*/
|
public SearchBuilder setStringQuery(String queryStr) {
|
QueryBuilder queryBuilder;
|
if (StrUtil.isNotEmpty(queryStr)) {
|
queryBuilder = QueryBuilders.queryStringQuery(queryStr);
|
} else {
|
queryBuilder = QueryBuilders.matchAllQuery();
|
}
|
searchBuilder.setQuery(queryBuilder);
|
return this;
|
}
|
|
/**
|
* 设置分页
|
* @param page 当前页数
|
* @param limit 每页显示数
|
*/
|
public SearchBuilder setPage(Integer page, Integer limit) {
|
if (page != null && limit != null) {
|
searchBuilder.setFrom((page - 1) * limit)
|
.setSize(limit);
|
}
|
return this;
|
}
|
|
/**
|
* 增加排序
|
* @param field 排序字段
|
* @param order 顺序方向
|
*/
|
public SearchBuilder addSort(String field, SortOrder order) {
|
if (StrUtil.isNotEmpty(field) && order != null) {
|
searchBuilder.addSort(field, order);
|
}
|
return this;
|
}
|
|
/**
|
* 设置高亮
|
* @param preTags 高亮处理前缀
|
* @param postTags 高亮处理后缀
|
*/
|
public SearchBuilder setHighlight(String field, String preTags, String postTags) {
|
if (StrUtil.isNotEmpty(field) && StrUtil.isNotEmpty(preTags) && StrUtil.isNotEmpty(postTags)) {
|
HighlightBuilder highlightBuilder = new HighlightBuilder();
|
highlightBuilder.field(field)
|
.preTags(preTags)
|
.postTags(postTags);
|
searchBuilder.highlighter(highlightBuilder);
|
}
|
return this;
|
}
|
|
/**
|
* 设置是否需要高亮处理
|
* @param isHighlighter 是否需要高亮处理
|
*/
|
public SearchBuilder setIsHighlight(Boolean isHighlighter) {
|
if (BooleanUtil.isTrue(isHighlighter)) {
|
this.setHighlight("*"
|
, HIGHLIGHTER_PRE_TAGS, HIGHLIGHTER_POST_TAGS);
|
}
|
return this;
|
}
|
|
/**
|
* 设置查询路由
|
* @param routing 路由数组
|
*/
|
public SearchBuilder setRouting(String... routing) {
|
if (ArrayUtil.isNotEmpty(routing)) {
|
searchBuilder.setRouting(routing);
|
}
|
return this;
|
}
|
|
/**
|
* 返回结果 SearchResponse
|
*/
|
public SearchResponse get() {
|
return searchBuilder.execute().actionGet();
|
}
|
|
/**
|
* 返回列表结果 List<JSONObject>
|
*/
|
public List<JSONObject> getList() {
|
return getList(this.get().getHits());
|
}
|
|
/**
|
* 返回分页结果 PageResult<JSONObject>
|
*/
|
public PageResult<JSONObject> getPage() {
|
return this.getPage(null, null);
|
}
|
|
/**
|
* 返回分页结果 PageResult<JSONObject>
|
* @param page 当前页数
|
* @param limit 每页显示
|
*/
|
public PageResult<JSONObject> getPage(Integer page, Integer limit) {
|
this.setPage(page, limit);
|
SearchResponse response = this.get();
|
SearchHits searchHits = response.getHits();
|
long totalCnt = searchHits.getTotalHits();
|
List<JSONObject> list = getList(searchHits);
|
return PageResult.<JSONObject>builder().data(list).code(0).count(totalCnt).build();
|
}
|
|
/**
|
* 返回JSON列表数据
|
*/
|
private List<JSONObject> getList(SearchHits searchHits) {
|
List<JSONObject> list = new ArrayList<>();
|
if (searchHits != null) {
|
searchHits.forEach(item -> {
|
JSONObject jsonObject = JSON.parseObject(item.getSourceAsString());
|
jsonObject.put("id", item.getId());
|
|
Map<String, HighlightField> highlightFields = item.getHighlightFields();
|
if (highlightFields != null) {
|
populateHighLightedFields(jsonObject, highlightFields);
|
}
|
list.add(jsonObject);
|
});
|
}
|
return list;
|
}
|
|
/**
|
* 组装高亮字符
|
* @param result 目标对象
|
* @param highlightFields 高亮配置
|
*/
|
private <T> void populateHighLightedFields(T result, Map<String, HighlightField> highlightFields) {
|
for (HighlightField field : highlightFields.values()) {
|
try {
|
String name = field.getName();
|
if (!name.endsWith(".keyword")) {
|
PropertyUtils.setProperty(result, field.getName(), concat(field.fragments()));
|
}
|
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
|
throw new ElasticsearchException("failed to set highlighted value for field: " + field.getName()
|
+ " with value: " + Arrays.toString(field.getFragments()), e);
|
}
|
}
|
}
|
/**
|
* 拼凑数组为字符串
|
*/
|
private String concat(Text[] texts) {
|
StringBuffer sb = new StringBuffer();
|
for (Text text : texts) {
|
sb.append(text.toString());
|
}
|
return sb.toString();
|
}
|
}
|