import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONObject;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: ES 查询工具类
* @Author: hank.zhang
* @Date: 2024/10/21 11:24
*/
@Data
public class ESQueryUtil {
/**
* 查询的条件 must 查询
*/
private ESQuery must = new ESQuery();
/**
* 排除的条件 must_not
*/
private ESQuery mustNot = new ESQuery();
/**
* 分页 - 查询当前页
*/
private Long page;
/**
* 分页 - 页面大小
*/
private Long pageSize;
/**
* 排序 - 倒叙排序的字段
*/
private List<String> desc = new ArrayList<>();
/**
* 排序 - 正序排序的字段
*/
private List<String> asc = new ArrayList<>();
/**
* 子文档查询 - 查询条件
*/
private QueryChild childQuery = new QueryChild();
/**
* or 的子查询条件
*/
private ESQuery should = new ESQuery();
/**
* 设置分页参数
*
* @param page 页码
* @param pageSize 页面大小
*/
public void setPageInfo(Integer page, Integer pageSize) {
this.page = page.longValue();
this.pageSize = pageSize.longValue();
}
/**
* 构建基础查询
*
* @return 查询条件封装
*/
public JSONObject buildQuery() {
JSONObject queryBody = new JSONObject();
// 2、排序
List<JSONObject> sortList = buildSort();
if (CollectionUtil.isNotEmpty(sortList)) {
queryBody.set("sort", sortList);
}
// 3、must 查询条件
JSONObject queryObj = new JSONObject();
List<JSONObject> must = new ArrayList<>(this.must.buildMust());
// 3.1、子文档查询
JSONObject childQuery = getChildQuery().buildChildQuery();
if (childQuery != null && !childQuery.isEmpty()) {
must.add(childQuery);
}
// 3.2、should查询 - 或查询
JSONObject should = buildShould();
if (should != null) {
must.add(should);
}
JSONObject queryArray = new JSONObject();
if(CollectionUtil.isNotEmpty(must)) {
queryArray.set("must", must);
}
// 4、must not
List<JSONObject> mustNot = this.mustNot.buildMust();
if(CollectionUtil.isNotEmpty(mustNot)) {
queryArray.set("must_not", mustNot);
}
queryObj.set("bool", queryArray);
queryBody.set("query", queryObj);
return queryBody;
}
/**
* 统计条件查询封装
*
* @param entries 查询对象
* @return 查询对象
*/
public JSONObject buildQueryCount(JSONObject entries) {
// 1、分页处理
entries.remove("sort");
return entries;
}
/**
* 构建分页查询对象
*
* @return 带上分页排序查询对象
*/
public JSONObject buildQueryPage() {
JSONObject entries = buildQuery();
// 1、分页处理
setPage(entries);
return entries;
}
/**
* 分页查询构建
*
* @param buildQuery 查询对象
* @return 带上分页排序查询对象
*/
public JSONObject buildQueryPage(JSONObject buildQuery) {
// 1、分页处理
setPage(buildQuery);
// 2、排序
List<JSONObject> sortList = buildSort();
if (CollectionUtil.isNotEmpty(sortList)) {
buildQuery.set("sort", sortList);
}
return buildQuery;
}
private JSONObject buildShould() {
List<JSONObject> buildMust = this.should.buildMust();
if (CollectionUtil.isEmpty(buildMust)) {
return null;
}
JSONObject boolObj = new JSONObject();
JSONObject bool = new JSONObject();
bool.set("minimum_should_match", 1);
bool.set("should", buildMust);
boolObj.set("bool", bool);
return boolObj;
}
private List<JSONObject> buildSort() {
List<JSONObject> sortList = new ArrayList<>();
if (CollectionUtil.isNotEmpty(this.getDesc())) {
sortList.addAll(this.getDesc().stream().map(v -> buildSortItem(v, "desc")).collect(Collectors.toList()));
}
if (CollectionUtil.isNotEmpty(this.getAsc())) {
sortList.addAll(this.getAsc().stream().map(v -> buildSortItem(v, "asc")).collect(Collectors.toList()));
}
return sortList;
}
private JSONObject buildSortItem(String fieldName, String sortType) {
JSONObject order = new JSONObject();
order.set("order", sortType);
JSONObject field = new JSONObject();
field.set(fieldName, order);
return field;
}
private void setPage(JSONObject queryBody) {
if (page == null || pageSize == null) {
return;
}
queryBody.set("size", pageSize);
queryBody.set("from", pageSize * (page - 1));
}
@Data
public static class QueryChild {
private ESQuery esQuery = new ESQuery();
private String childType;
public JSONObject buildChildQuery() {
if (childType == null || this.esQuery.buildMust().isEmpty()) {
return null;
}
JSONObject object = new JSONObject();
JSONObject hasChild = new JSONObject();
if (childType != null) {
JSONObject must = new JSONObject();
must.set("must", this.esQuery.buildMust());
JSONObject bool = new JSONObject();
bool.set("bool", must);
hasChild.set("type", this.getChildType());
hasChild.set("query", bool);
}
object.set("has_child", hasChild);
return object;
}
}
@Data
public static class ESQuery {
/**
* 等值查询 <查询的字段名字, 查询字段对应的值>
*/
private Map<String, Object> eq = new HashMap<>();
/**
* 迷糊查询 <查询的字段名字, 查询字段对应的值> 底层使用 fuzziness 查询
*/
private Map<String, String> fuzziness = new HashMap<>();
/**
* 范围查询
*/
private List<RangQuery> rangeE = new ArrayList<>();
/**
* 某个字段必须存在
*/
private List<String> exists = new ArrayList<>();
/**
* in 查询
*/
private Map<String, List<?>> in = new HashMap<>();
/**
* 迷糊查询 可用通配符 底层使用 es 的 wildcard 查询
* Wildcard查询是一种基于通配符的查询方式,通配符包括 *(匹配任意字符)和 ?(匹配单个字符)
*/
private Map<String, String> wildcard = new HashMap<>();
/**
* 迷糊查询 完全匹配查询,查询更类似于 mysql的模糊查询,不过这个无需拼接通配符 底层使用 es 的 match_phrase 查询
*/
private Map<String, String> like = new HashMap<>();
/**
* 通过正则表达式进行匹配查询
*/
private Map<String, String> regexp = new HashMap<>();
public List<JSONObject> buildMust() {
List<JSONObject> must = new ArrayList<>();
// 1、等值查询
if (CollectionUtil.isNotEmpty(this.eq)) {
must.addAll(this.eq.entrySet().stream().map(v -> buildTerm(v.getKey(), v.getValue())).collect(Collectors.toList()));
}
// 2、模糊查询 - 使用es: match_phrase
if (CollectionUtil.isNotEmpty(this.like)) {
must.addAll(buildMatchPhrase());
}
// 3、范围查询 - 使用es:range
if (CollectionUtil.isNotEmpty(this.rangeE)) {
must.add(buildRange());
}
// 4、in 查询 - 使用es:terms
if (CollectionUtil.isNotEmpty(this.in)) {
must.addAll(buildIn());
}
// 5、exists 某个字段存在 - 使用es: exists
if (CollectionUtil.isNotEmpty(this.exists)) {
must.addAll(buildExists());
}
// 6、模糊查询 查询 - 使用es: wildcard
if (CollectionUtil.isNotEmpty(wildcard)) {
must.addAll(buildWildcard());
}
// 7、模糊查询 查询 - 使用es: fuzziness
if (CollectionUtil.isNotEmpty(fuzziness)) {
must.addAll(buildFuzziness());
}
// 8、正则查询 - 使用es:regexp
if (CollectionUtil.isNotEmpty(regexp)) {
must.addAll(buildRegexp());
}
return must;
}
private List<JSONObject> buildRegexp(){
return this.regexp.entrySet().stream().map(v -> {
JSONObject regexp = new JSONObject();
JSONObject field = new JSONObject();
field.set(v.getKey(), v.getValue());
regexp.set("regexp", field);
return regexp;
}).collect(Collectors.toList());
}
private List<JSONObject> buildMatchPhrase(){
return this.like.entrySet().stream().map(v -> {
JSONObject matchPhrase = new JSONObject();
JSONObject field = new JSONObject();
field.set(v.getKey(), v.getValue());
matchPhrase.set("match_phrase", field);
return matchPhrase;
}).collect(Collectors.toList());
}
private List<JSONObject> buildExists() {
return this.exists.stream().map(v -> {
JSONObject exists = new JSONObject();
JSONObject field = new JSONObject();
field.set("field", v);
exists.set("exists", field);
return exists;
}).collect(Collectors.toList());
}
private List<JSONObject> buildWildcard() {
return this.wildcard.entrySet().stream().map(v -> {
JSONObject wildcard = new JSONObject();
JSONObject wildcardItem = new JSONObject();
JSONObject item = new JSONObject();
item.set("value", v.getValue());
item.set("case_insensitive", true);
wildcardItem.set(v.getKey() + ".keyword", item);
wildcard.set("wildcard", wildcardItem);
return wildcard;
}).collect(Collectors.toList());
}
private List<JSONObject> buildIn() {
return this.in.entrySet().stream().map(v -> {
JSONObject terms = new JSONObject();
JSONObject item = new JSONObject();
item.set(v.getKey(), v.getValue());
terms.set("terms", item);
return terms;
}).collect(Collectors.toList());
}
private JSONObject buildRange() {
JSONObject rangeObj = new JSONObject();
JSONObject rangeItems = new JSONObject();
List<RangQuery> rangeE = this.getRangeE();
rangeE.forEach(v -> rangeItems.set(v.getFieldName(), v.buildRange()));
rangeObj.set("range", rangeItems);
return rangeObj;
}
private List<JSONObject> buildFuzziness() {
return this.like.entrySet().stream().map(v -> buildLikeItem(v.getKey(), v.getValue())).collect(Collectors.toList());
}
private JSONObject buildLikeItem(String key, Object val) {
JSONObject match = new JSONObject();
JSONObject filedQuery = new JSONObject();
JSONObject valObj = new JSONObject();
valObj.set("query", val);
valObj.set("fuzziness", "AUTO");
filedQuery.set(key, valObj);
match.set("match", filedQuery);
return match;
}
private JSONObject buildTerm(String key, Object val) {
JSONObject must = new JSONObject();
JSONObject valObj = new JSONObject();
valObj.set(key, val);
must.set("term", valObj);
return must;
}
}
@Data
public static class RangQuery {
/**
* 查询字段名字
*/
private String fieldName;
/**
* 字段查询开始 - 值
*/
private Object rangStart;
/**
* 字段查询结束 - 值
*/
private Object rangEnd;
public RangQuery() {
}
public RangQuery(String fieldName, Object rangStart, Object rangEnd) {
this.fieldName = fieldName;
this.rangStart = rangStart;
this.rangEnd = rangEnd;
}
private JSONObject buildRange() {
JSONObject rangeItemVal = new JSONObject();
rangeItemVal.set("gte", this.rangStart);
rangeItemVal.set("lte", this.rangEnd);
return rangeItemVal;
}
}
}
最后修改于 2024-10-29 07:25:50
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

