v2.0-beta1

调整重建索引超时时间默认值为72小时,避免小白踩坑超时,并且可配置.
彻底搞定5种嵌套及多层级嵌套
This commit is contained in:
xpc1024 2023-02-28 18:03:46 +08:00
parent 572591aa31
commit 848ba0c7b5
15 changed files with 274 additions and 226 deletions

View File

@ -74,4 +74,11 @@ public @interface IndexName {
* @return 默认子类
*/
Class<?> childClass() default DefaultChildClass.class;
/**
* 路由
*
* @return CRUD作用的路由
*/
String routing() default "";
}

View File

@ -1,5 +1,7 @@
package cn.easyes.annotation.rely;
import java.util.Arrays;
/**
* Es支持的数据类型枚举
* <p>
@ -67,4 +69,17 @@ public enum FieldType {
public String getType() {
return type;
}
/**
* 根据类型字符串获取对应枚举
*
* @param type 类型字符串
* @return 对应枚举
*/
public static FieldType getByType(String type) {
return Arrays.stream(FieldType.values())
.filter(v -> v.getType().equals(type))
.findFirst()
.orElse(FieldType.KEYWORD_TEXT);
}
}

View File

@ -55,10 +55,6 @@ public interface BaseEsConstants {
* 冒号
*/
String COLON = ":";
/**
* 逗号分隔符
*/
String COMMA_SEPARATOR = ",";
/**
* ee内置es分布式锁索引名称
*/
@ -135,10 +131,6 @@ public interface BaseEsConstants {
* 默认返回数
*/
Integer DEFAULT_SIZE = 10000;
/**
* es默认得分字段
*/
String SCORE_FIELD = "_score";
/**
* DSL语句前缀
*/
@ -200,10 +192,6 @@ public interface BaseEsConstants {
* 默认最小匹配百分比
*/
int DEFAULT_MIN_SHOULD_MATCH = 60;
/**
* 百分比符号
*/
String PERCENT = "%";
/**
* 嵌套类型 path和field连接符
*/

View File

@ -36,6 +36,10 @@ public class EntityInfo {
* 索引名称(原索引名)
*/
private String indexName;
/**
* 配置的路由
*/
private String routing;
/**
* 新索引名(由EE在更新索引时自动创建)
*/
@ -132,6 +136,10 @@ public class EntityInfo {
* 实体字段->高亮返回结果 键值对
*/
private final Map<String, String> highlightFieldMap = new HashMap<>();
/**
* 实体字段名->es字段类型
*/
private final Map<String, String> fieldTypeMap = new HashMap<>();
/**
* 实体字段->es实际字段映射
*/
@ -152,6 +160,10 @@ public class EntityInfo {
* 嵌套类型 path和class对应关系
*/
private final Map<String, Class<?>> pathClassMap = new HashMap<>();
/**
* 嵌套类型 实体字段名->字段类型
*/
private final Map<Class<?>, Map<String, String>> nestedClassFieldTypeMap = new HashMap<>();
/**
* 嵌套类型 实体字段->es实际字段映射
*/

View File

@ -65,7 +65,7 @@ public interface Nested<Param, Children> extends Serializable {
Children should(boolean condition, Consumer<Param> consumer);
default Children filter(Consumer<Param> consumer) {
return should(true, consumer);
return filter(true, consumer);
}
/**
@ -78,7 +78,7 @@ public interface Nested<Param, Children> extends Serializable {
Children filter(boolean condition, Consumer<Param> consumer);
default Children mustNot(Consumer<Param> consumer) {
return should(true, consumer);
return mustNot(true, consumer);
}
/**

View File

@ -25,6 +25,10 @@ public class GlobalConfig {
* process index mode Smoothly by default 索引处理模式 默认开启平滑模式
*/
private ProcessIndexStrategyEnum processIndexMode = ProcessIndexStrategyEnum.SMOOTHLY;
/**
* Rebuild index timeout unit: hour, default: 72 重建索引超时时间 单位小时,默认72
*/
private int reindexTimeOutHours = 72;
/**
* process index blocking main thread true by default 异步处理索引是否阻塞主线程 默认阻塞
*/
@ -43,7 +47,6 @@ public class GlobalConfig {
* 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数 若数据量过大,重建索引数据迁移时间超过60*(180/60)=180分钟时,可调大此参数值 此参数值决定多久重试一次 单位:
*/
private int activeReleaseIndexFixedDelay = 180;
/**
* es db config 数据库配置
*/

View File

@ -135,10 +135,12 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
@Override
public Children or(boolean condition) {
if (!paramQueue.isEmpty()) {
Param param = paramQueue.peekLast();
// 需要将其前一同level节点prevQueryType修改为or_should
for (int i = paramQueue.size() - 1; i >= 0; i--) {
Param param = paramQueue.get(i);
if (Objects.equals(level, param.getLevel())) {
param.setPrevQueryType(OR_SHOULD);
break;
}
}
return addParam(condition, OR, null, null, null);
@ -655,6 +657,7 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
* @param boost 权重
*/
private void addBaseParam(Param param, EsQueryTypeEnum queryTypeEnum, String column, Object val, Float boost) {
// 基本值设置
param.setId(UUID.randomUUID().toString());
Optional.ofNullable(parentId).ifPresent(param::setParentId);
param.setPrevQueryType(prevQueryType);
@ -662,18 +665,62 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
param.setVal(val);
param.setColumn(column);
param.setBoost(boost);
param.setLevel(level);
// 入队之前需要先对MP中的拼接or()特殊处理之所以在此处处理,是因为可以少遍历一遍树 节省OLog(N) 时间复杂度
if (!paramQueue.isEmpty()) {
Param prev = paramQueue.peekLast();
if (OR.equals(prev.getQueryTypeEnum())) {
// 上一节点是拼接or() 则修改当前节点的prevQueryType为OR_SHOULD 让其走should查询
param.setPrevQueryType(OR_SHOULD);
}
}
// 入队之前需要先对MP中的拼接or()特殊处理
processOr(param);
paramQueue.add(param);
}
/**
* 追加基础嵌套
*
* @param param 参数
* @param queryTypeEnum 查询类型
* @param consumer 消费者
*/
private void addBaseNested(Param param, EsQueryTypeEnum queryTypeEnum, Consumer<Children> consumer) {
// 基本值设置
param.setId(UUID.randomUUID().toString());
Optional.ofNullable(parentId).ifPresent(param::setParentId);
param.setQueryTypeEnum(queryTypeEnum);
param.setLevel(level);
param.setPrevQueryType(queryTypeEnum);
// 入队之前需要先对MP中的拼接or()特殊处理
processOr(param);
paramQueue.add(param);
this.parentId = param.getId();
parentIdQueue.push(parentId);
level++;
consumer.accept(instance());
// 深度优先在consumer条件消费完后会来执行这里 此时parentId需要重置 至于为什么,比较烧脑 可断点打在consumer前后观察一波
level--;
if (!parentIdQueue.isEmpty()) {
this.parentId = parentIdQueue.pollLast();
}
if (level == 0) {
// 仙人板板 根节点
this.parentId = null;
}
}
/**
* 特殊处理拼接or
*
* @param param 参数
*/
private void processOr(Param param) {
if (!paramQueue.isEmpty()) {
Param prev = paramQueue.peekLast();
if (OR.equals(prev.getQueryTypeEnum())) {
// 上一节点是拼接or() 需要重置其prevQueryType类型,让其走should查询
param.setPrevQueryType(OR_SHOULD);
}
}
}
/**
* 追加查询参数
@ -763,39 +810,6 @@ public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T,
}
/**
* 追加基础嵌套
*
* @param param 参数
* @param queryTypeEnum 查询类型
* @param consumer 消费者
*/
private void addBaseNested(Param param, EsQueryTypeEnum queryTypeEnum, Consumer<Children> consumer) {
param.setId(UUID.randomUUID().toString());
Optional.ofNullable(parentId).ifPresent(param::setParentId);
param.setQueryTypeEnum(queryTypeEnum);
level++;
param.setLevel(level);
paramQueue.add(param);
this.parentId = param.getId();
parentIdQueue.push(parentId);
prevQueryTypeQueue.push(queryTypeEnum);
consumer.accept(instance());
// 深度优先在consumer条件消费完后会来执行这里 此时parentId需要重置 至于为什么 可断点打在consumer前后观察一波 整个框架最难的地方就在此
level--;
if (!parentIdQueue.isEmpty()) {
this.parentId = parentIdQueue.pollLast();
}
if (!prevQueryTypeQueue.isEmpty()) {
this.prevQueryType = prevQueryTypeQueue.pollLast();
}
if (level == 0) {
// 仙人板板 根节点
this.parentId = null;
this.prevQueryType = AND_MUST;
}
}
/**
* 重载追加嵌套条件
*

View File

@ -213,6 +213,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
public String getSource(Wrapper<T> wrapper) {
// 获取由本框架生成的es查询参数 用于验证生成语法的正确性
SearchRequest searchRequest = new SearchRequest(getIndexNames(wrapper.indexNames));
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
SearchSourceBuilder searchSourceBuilder = WrapperProcessor.buildSearchSourceBuilder(wrapper, entityClass);
searchRequest.source(searchSourceBuilder);
return Optional.ofNullable(searchRequest.source())
@ -292,6 +293,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
} else {
// 不去重,直接count获取,效率更高
CountRequest countRequest = new CountRequest(getIndexNames(wrapper.indexNames));
Optional.ofNullable(getRouting()).ifPresent(countRequest::routing);
QueryBuilder queryBuilder = Optional.ofNullable(wrapper.searchSourceBuilder)
.map(SearchSourceBuilder::query)
.orElseGet(() -> WrapperProcessor.initBoolQueryBuilder(wrapper.paramQueue, entityClass));
@ -369,6 +371,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
@Override
public Integer delete(Wrapper<T> wrapper) {
DeleteByQueryRequest request = new DeleteByQueryRequest(getIndexNames(wrapper.indexNames));
Optional.ofNullable(getRouting()).ifPresent(request::setRouting);
BoolQueryBuilder boolQueryBuilder = WrapperProcessor.initBoolQueryBuilder(wrapper.paramQueue, entityClass);
request.setQuery(boolQueryBuilder);
BulkByScrollResponse bulkResponse;
@ -467,6 +470,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
// 构造查询参数
List<String> stringIdList = idList.stream().map(Object::toString).collect(Collectors.toList());
SearchRequest searchRequest = new SearchRequest(getIndexNames(indexName));
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termsQuery(DEFAULT_ES_ID_NAME, stringIdList));
sourceBuilder.size(idList.size());
@ -574,6 +578,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
// 更新mapping
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
if (Objects.isNull(wrapper.mapping)) {
Assert.notEmpty(wrapper.esIndexParamList, String.format("update index: %s failed, because of empty update args", indexName));
Map<String, Object> mapping = IndexUtils.initMapping(EntityInfoHelper.getEntityInfo(entityClass), wrapper.esIndexParamList);
@ -601,6 +606,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private Integer doInsert(T entity, String indexName) {
// 构建请求入参
IndexRequest indexRequest = buildIndexRequest(entity, indexName);
Optional.ofNullable(getRouting()).ifPresent(indexRequest::routing);
indexRequest.setRefreshPolicy(getRefreshPolicy());
try {
@ -629,6 +635,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private Integer doInsertBatch(Collection<T> entityList, String indexName) {
// 构建批量请求参数
BulkRequest bulkRequest = new BulkRequest();
Optional.ofNullable(getRouting()).ifPresent(bulkRequest::routing);
bulkRequest.setRefreshPolicy(getRefreshPolicy());
entityList.forEach(entity -> {
IndexRequest indexRequest = buildIndexRequest(entity, indexName);
@ -649,6 +656,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
*/
private Integer doDeleteById(Serializable id, String indexName) {
DeleteRequest deleteRequest = generateDelRequest(id, indexName);
Optional.ofNullable(getRouting()).ifPresent(deleteRequest::routing);
deleteRequest.setRefreshPolicy(getRefreshPolicy());
try {
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
@ -671,6 +679,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
*/
private Integer doDeleteBatchIds(Collection<? extends Serializable> idList, String indexName) {
BulkRequest bulkRequest = new BulkRequest();
Optional.ofNullable(getRouting()).ifPresent(bulkRequest::routing);
bulkRequest.setRefreshPolicy(getRefreshPolicy());
idList.forEach(id -> {
DeleteRequest deleteRequest = generateDelRequest(id, indexName);
@ -690,6 +699,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private Integer doUpdateById(T entity, String idValue, String indexName) {
// 构建更新请求参数
UpdateRequest updateRequest = buildUpdateRequest(entity, idValue, indexName);
Optional.ofNullable(getRouting()).ifPresent(updateRequest::routing);
updateRequest.setRefreshPolicy(getRefreshPolicy());
// 执行更新
@ -715,6 +725,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private Integer doUpdateBatchByIds(Collection<T> entityList, String indexName) {
// 封装批量请求参数
BulkRequest bulkRequest = new BulkRequest();
Optional.ofNullable(getRouting()).ifPresent(bulkRequest::routing);
bulkRequest.setRefreshPolicy(getRefreshPolicy());
entityList.forEach(entity -> {
String idValue = getIdValue(entity);
@ -748,6 +759,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
// 批量更新
BulkRequest bulkRequest = new BulkRequest();
Optional.ofNullable(getRouting()).ifPresent(bulkRequest::routing);
bulkRequest.setRefreshPolicy(getRefreshPolicy());
Method getId = BaseCache.getterMethod(entityClass, getRealIdFieldName());
EntityInfo entityInfo = EntityInfoHelper.getEntityInfo(entityClass);
@ -782,6 +794,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private T doSelectById(Serializable id, String indexName) {
// 构造查询参数
SearchRequest searchRequest = new SearchRequest(indexName);
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery(DEFAULT_ES_ID_NAME, id));
searchRequest.source(searchSourceBuilder);
@ -807,6 +820,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private SearchResponse getSearchResponse(Wrapper<T> wrapper, Object[] searchAfter) {
// 构建es restHighLevelClient 查询参数
SearchRequest searchRequest = new SearchRequest(getIndexNames(wrapper.indexNames));
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
// 用户在wrapper中指定的混合查询条件优先级最高
SearchSourceBuilder searchSourceBuilder = Optional.ofNullable(wrapper.searchSourceBuilder)
@ -859,6 +873,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private List<T> selectListByUpdateWrapper(Wrapper<T> wrapper, String indexName) {
// 构建查询条件
SearchRequest searchRequest = new SearchRequest(indexName);
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
SearchSourceBuilder searchSourceBuilder;
if (Objects.isNull(wrapper.searchSourceBuilder)) {
searchSourceBuilder = new SearchSourceBuilder();
@ -881,7 +896,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
searchRequest.source(searchSourceBuilder);
printDSL(searchRequest);
try {
// 查询数据明细
// 查询数据明细
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
printResponseErrors(response);
SearchHit[] searchHits = parseSearchHitArray(response);
@ -1126,6 +1141,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
*/
private SearchHit[] getSearchHitArray(Wrapper<T> wrapper) {
SearchRequest searchRequest = new SearchRequest(getIndexNames(wrapper.indexNames));
Optional.ofNullable(getRouting()).ifPresent(searchRequest::routing);
// 用户在wrapper中指定的混合查询条件优先级最高
SearchSourceBuilder searchSourceBuilder = Objects.isNull(wrapper.searchSourceBuilder) ?
@ -1209,7 +1225,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
updateParamList.forEach(esUpdateParam -> {
String realField = FieldUtils.getRealFieldNotConvertId(esUpdateParam.getField(),
EntityInfoHelper.getEntityInfo(entityClass).getMappingColumnMap(),
GlobalConfigCache.getGlobalConfig().getDbConfig());
GlobalConfigCache.getGlobalConfig().getDbConfig().isMapUnderscoreToCamelCase());
jsonObject.put(realField, esUpdateParam.getValue());
});
return JSON.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue);
@ -1445,11 +1461,20 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
}
/**
* 父子
* 获取路由
*
* @return 路由
*/
private String getRouting() {
return EntityInfoHelper.getEntityInfo(entityClass).getRouting();
}
/**
* 父子文档获取路由
*
* @param entity 实体对象
* @param joinFieldClass join字段类
* @return
* @return 路由
*/
private String getRouting(T entity, Class<?> joinFieldClass) {
// 父子类型-子文档,设置路由

View File

@ -1,12 +1,10 @@
package cn.easyes.core.core;
import cn.easyes.annotation.rely.FieldType;
import cn.easyes.common.enums.AggregationTypeEnum;
import cn.easyes.common.enums.EsQueryTypeEnum;
import cn.easyes.common.utils.*;
import cn.easyes.core.biz.*;
import cn.easyes.core.cache.GlobalConfigCache;
import cn.easyes.core.config.GlobalConfig;
import cn.easyes.core.toolkit.EntityInfoHelper;
import cn.easyes.core.toolkit.FieldUtils;
import cn.easyes.core.toolkit.TreeBuilder;
@ -38,6 +36,7 @@ import java.util.stream.Collectors;
import static cn.easyes.common.constants.BaseEsConstants.*;
import static cn.easyes.common.enums.EsQueryTypeEnum.*;
import static cn.easyes.core.toolkit.FieldUtils.*;
/**
* 核心 wrapper处理类
@ -74,60 +73,14 @@ public class WrapperProcessor {
* @param entityClass 实体类
*/
public static BoolQueryBuilder initBoolQueryBuilder(List<Param> paramList, Class<?> entityClass) {
// 数据预处理
List<Param> rootList = new ArrayList<>();
preProcessData(paramList, rootList, entityClass);
// 建立参数森林无根树
List<Param> rootList = paramList.stream().filter(i -> Objects.isNull(i.getParentId())).collect(Collectors.toList());
TreeBuilder treeBuilder = new TreeBuilder(rootList, paramList);
List<Param> tree = (List<Param>) treeBuilder.build();
BoolQueryBuilder rootBool = QueryBuilders.boolQuery();
// 对森林的每个根节点递归封装 这里看似简单实则很绕很烧脑 整个框架的核心 主要依托树的递归 深度优先遍历 森林
return getBool(tree, rootBool);
}
/***
* 数据预处理 原始数据转换为目标数据
* @param paramList 参数列表
* @param rootList 子树根
* @param entityClass 实体类
*/
private static void preProcessData(List<Param> paramList, List<Param> rootList, Class<?> entityClass) {
EntityInfo entityInfo = EntityInfoHelper.getEntityInfo(entityClass);
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
Map<String, String> fieldTypeMap = entityInfo.getFieldList().stream()
.collect(Collectors.toMap(EntityFieldInfo::getColumn, item -> Optional.ofNullable(item.getFieldType())
.map(FieldType::getType).orElse(FieldType.KEYWORD_TEXT.getType())));
// TODO 嵌套类型中的字段名称及自动智能拼接.keyword后缀待近期补充 以及嵌套类型自定义字段处理
Map<Class<?>, List<EntityFieldInfo>> nestedFieldListMap = entityInfo.getNestedFieldListMap();
paramList.forEach(param -> {
// 驼峰及自定义字段转换
String realField = FieldUtils.getRealField(param.getColumn(), entityInfo.getMappingColumnMap(), dbConfig);
param.setColumn(realField);
if (ArrayUtils.isNotEmpty(param.getColumns())) {
String[] columns = FieldUtils.getRealFields(param.getColumns(), entityInfo.getMappingColumnMap(), dbConfig);
param.setColumns(columns);
}
if (HAS_CHILD.equals(param.getQueryTypeEnum()) || HAS_PARENT.equals(param.getQueryTypeEnum())) {
String realPath = FieldUtils.getRealField(param.getExt1().toString(), entityInfo.getMappingColumnMap(), dbConfig);
param.setExt1(realPath);
}
// 是否需要智能拼接.keyword后缀
Optional.ofNullable(fieldTypeMap.get(realField))
.ifPresent(fieldType -> {
if (FieldType.KEYWORD_TEXT.getType().equals(fieldType)) {
param.setNeedAddKeywordSuffix(true);
}
});
if (param.getParentId() == null) {
// 仙人板板
rootList.add(param);
}
});
// 对森林的每个根节点递归封装 这里看似简单实则很绕很烧脑 整个框架的核心 主要依托树的递归 深度优先遍历 森林 还原lambda条件构造语句
return getBool(tree, rootBool, EntityInfoHelper.getEntityInfo(entityClass), null);
}
/**
@ -137,34 +90,39 @@ public class WrapperProcessor {
* @param param 查询参数
*/
@SneakyThrows
private static void initBool(BoolQueryBuilder bool, Param param) {
private static void initBool(BoolQueryBuilder bool, Param param, EntityInfo entityInfo,
Map<String, String> mappingColumnMap, Map<String, String> fieldTypeMap) {
List<Param> children = (List<Param>) param.getChildren();
QueryBuilder queryBuilder;
RangeQueryBuilder rangeBuilder;
String finalField;
String realField;
switch (param.getQueryTypeEnum()) {
case OR:
// 渣男行为,*完就不认人了,因为拼接OR已处理过了 直接跳过
break;
case TERM:
finalField = getFinalField(param.getColumn(), param.isNeedAddKeywordSuffix());
queryBuilder = QueryBuilders.termQuery(finalField, param.getVal()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
queryBuilder = QueryBuilders.termQuery(realField, param.getVal()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case MATCH:
queryBuilder = QueryBuilders.matchQuery(param.getColumn(), param.getVal()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.matchQuery(realField, param.getVal()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case MATCH_PHRASE:
queryBuilder = QueryBuilders.matchPhraseQuery(param.getColumn(), param.getVal()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.matchPhraseQuery(realField, param.getVal()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case MATCH_PHRASE_PREFIX:
queryBuilder = QueryBuilders.matchPhrasePrefixQuery(param.getColumn(), param.getVal()).boost(param.getBoost()).maxExpansions((int) param.getExt1());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.matchPhrasePrefixQuery(realField, param.getVal()).boost(param.getBoost()).maxExpansions((int) param.getExt1());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case MULTI_MATCH:
queryBuilder = QueryBuilders.multiMatchQuery(param.getVal(), param.getColumns()).operator((Operator) param.getExt1()).minimumShouldMatch(String.valueOf(param.getExt2()));
String[] realFields = getRealFields(param.getColumns(), mappingColumnMap);
queryBuilder = QueryBuilders.multiMatchQuery(param.getVal(), realFields).operator((Operator) param.getExt1()).minimumShouldMatch(String.valueOf(param.getExt2()));
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case MATCH_ALL:
@ -172,111 +130,120 @@ public class WrapperProcessor {
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case QUERY_STRING:
queryBuilder = QueryBuilders.queryStringQuery(param.getColumn()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
queryBuilder = QueryBuilders.queryStringQuery(realField).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case PREFIX:
queryBuilder = QueryBuilders.prefixQuery(param.getColumn(), (String) param.getVal()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.prefixQuery(realField, (String) param.getVal()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GT:
rangeBuilder = QueryBuilders.rangeQuery(param.getColumn()).gt(param.getVal()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
rangeBuilder = QueryBuilders.rangeQuery(realField).gt(param.getVal()).boost(param.getBoost());
Optional.ofNullable(param.getExt1()).ifPresent(ext1 -> rangeBuilder.timeZone(((ZoneId) ext1).getId()));
Optional.ofNullable(param.getExt2()).ifPresent(ext2 -> rangeBuilder.format(ext2.toString()));
setBool(bool, rangeBuilder, param.getPrevQueryType());
break;
case GE:
rangeBuilder = QueryBuilders.rangeQuery(param.getColumn()).gte(param.getVal()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
rangeBuilder = QueryBuilders.rangeQuery(realField).gte(param.getVal()).boost(param.getBoost());
Optional.ofNullable(param.getExt1()).ifPresent(ext1 -> rangeBuilder.timeZone(((ZoneId) ext1).getId()));
Optional.ofNullable(param.getExt2()).ifPresent(ext2 -> rangeBuilder.format(ext2.toString()));
setBool(bool, rangeBuilder, param.getPrevQueryType());
break;
case LT:
rangeBuilder = QueryBuilders.rangeQuery(param.getColumn()).lt(param.getVal()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
rangeBuilder = QueryBuilders.rangeQuery(realField).lt(param.getVal()).boost(param.getBoost());
Optional.ofNullable(param.getExt1()).ifPresent(ext1 -> rangeBuilder.timeZone(((ZoneId) ext1).getId()));
Optional.ofNullable(param.getExt2()).ifPresent(ext2 -> rangeBuilder.format(ext2.toString()));
setBool(bool, rangeBuilder, param.getPrevQueryType());
break;
case LE:
rangeBuilder = QueryBuilders.rangeQuery(param.getColumn()).lte(param.getVal()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
rangeBuilder = QueryBuilders.rangeQuery(realField).lte(param.getVal()).boost(param.getBoost());
Optional.ofNullable(param.getExt1()).ifPresent(ext1 -> rangeBuilder.timeZone(((ZoneId) ext1).getId()));
Optional.ofNullable(param.getExt2()).ifPresent(ext2 -> rangeBuilder.format(ext2.toString()));
setBool(bool, rangeBuilder, param.getPrevQueryType());
break;
case BETWEEN:
rangeBuilder = QueryBuilders.rangeQuery(param.getColumn()).gte(param.getExt1()).lte(param.getExt2()).boost(param.getBoost());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
rangeBuilder = QueryBuilders.rangeQuery(realField).gte(param.getExt1()).lte(param.getExt2()).boost(param.getBoost());
Optional.ofNullable(param.getExt3()).ifPresent(ext3 -> rangeBuilder.timeZone(((ZoneId) ext3).getId()));
Optional.ofNullable(param.getExt4()).ifPresent(ext4 -> rangeBuilder.format(ext4.toString()));
setBool(bool, rangeBuilder, param.getPrevQueryType());
break;
case WILDCARD:
finalField = getFinalField(param.getColumn(), param.isNeedAddKeywordSuffix());
queryBuilder = QueryBuilders.wildcardQuery(finalField, param.getVal().toString());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
queryBuilder = QueryBuilders.wildcardQuery(realField, param.getVal().toString());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case TERMS:
finalField = getFinalField(param.getColumn(), param.isNeedAddKeywordSuffix());
queryBuilder = QueryBuilders.termsQuery(finalField, (Collection<?>) param.getVal());
realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap);
queryBuilder = QueryBuilders.termsQuery(realField, (Collection<?>) param.getVal());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case EXISTS:
queryBuilder = QueryBuilders.existsQuery(param.getColumn()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.existsQuery(realField).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GEO_BOUNDING_BOX:
queryBuilder = QueryBuilders.geoBoundingBoxQuery(param.getColumn()).setCorners((GeoPoint) param.getExt1(), (GeoPoint) param.getExt2()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.geoBoundingBoxQuery(realField).setCorners((GeoPoint) param.getExt1(), (GeoPoint) param.getExt2()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GEO_DISTANCE:
GeoDistanceQueryBuilder geoDistanceBuilder = QueryBuilders.geoDistanceQuery(param.getColumn()).point((GeoPoint) param.getExt2()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
GeoDistanceQueryBuilder geoDistanceBuilder = QueryBuilders.geoDistanceQuery(realField).point((GeoPoint) param.getExt2()).boost(param.getBoost());
MyOptional.ofNullable(param.getExt1()).ifPresent(ext1 -> geoDistanceBuilder.distance((double) param.getVal(), (DistanceUnit) ext1), () -> geoDistanceBuilder.distance((String) param.getVal()));
queryBuilder = geoDistanceBuilder;
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GEO_POLYGON:
queryBuilder = QueryBuilders.geoPolygonQuery(param.getColumn(), (List<GeoPoint>) param.getVal());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.geoPolygonQuery(realField, (List<GeoPoint>) param.getVal());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GEO_SHAPE_ID:
queryBuilder = QueryBuilders.geoShapeQuery(param.getColumn(), param.getVal().toString()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.geoShapeQuery(realField, param.getVal().toString()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case GEO_SHAPE:
queryBuilder = QueryBuilders.geoShapeQuery(param.getColumn(), (Geometry) param.getVal()).relation((ShapeRelation) param.getExt1()).boost(param.getBoost());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = QueryBuilders.geoShapeQuery(realField, (Geometry) param.getVal()).relation((ShapeRelation) param.getExt1()).boost(param.getBoost());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case HAS_CHILD:
queryBuilder = new HasChildQueryBuilder(param.getExt1().toString(), QueryBuilders.matchQuery(param.getExt1().toString() + PATH_FIELD_JOIN + param.getColumn(), param.getVal()).boost(param.getBoost()), (ScoreMode) param.getExt2());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = new HasChildQueryBuilder(param.getExt1().toString(), QueryBuilders.matchQuery(param.getExt1().toString() + PATH_FIELD_JOIN + realField, param.getVal()).boost(param.getBoost()), (ScoreMode) param.getExt2());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case HAS_PARENT:
queryBuilder = new HasParentQueryBuilder(param.getExt1().toString(), QueryBuilders.matchQuery(param.getExt1().toString() + PATH_FIELD_JOIN + param.getColumn(), param.getVal()).boost(param.getBoost()), (boolean) param.getExt2());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = new HasParentQueryBuilder(param.getExt1().toString(), QueryBuilders.matchQuery(param.getExt1().toString() + PATH_FIELD_JOIN + realField, param.getVal()).boost(param.getBoost()), (boolean) param.getExt2());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case PARENT_ID:
queryBuilder = new ParentIdQueryBuilder(param.getColumn(), param.getVal().toString());
realField = getRealField(param.getColumn(), mappingColumnMap);
queryBuilder = new ParentIdQueryBuilder(realField, param.getVal().toString());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
// 下面五种嵌套类型 需要对孩子节点递归处理
case AND_MUST:
queryBuilder = getBool(children, QueryBuilders.boolQuery());
setBool(bool, queryBuilder, AND_MUST);
break;
case FILTER:
queryBuilder = getBool(children, QueryBuilders.boolQuery());
setBool(bool, queryBuilder, FILTER);
break;
case MUST_NOT:
queryBuilder = getBool(children, QueryBuilders.boolQuery());
setBool(bool, queryBuilder, MUST_NOT);
break;
case OR_SHOULD:
queryBuilder = getBool(children, QueryBuilders.boolQuery());
setBool(bool, queryBuilder, OR_SHOULD);
queryBuilder = getBool(children, QueryBuilders.boolQuery(), entityInfo, null);
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
case NESTED:
queryBuilder = getBool(children, QueryBuilders.boolQuery());
queryBuilder = QueryBuilders.nestedQuery(param.getColumn(), queryBuilder, (ScoreMode) param.getVal());
realField = getRealField(param.getColumn(), mappingColumnMap);
String[] split = param.getColumn().split("\\.");
queryBuilder = getBool(children, QueryBuilders.boolQuery(), entityInfo, split[split.length - 1]);
queryBuilder = QueryBuilders.nestedQuery(realField, queryBuilder, (ScoreMode) param.getVal());
setBool(bool, queryBuilder, param.getPrevQueryType());
break;
default:
@ -285,7 +252,6 @@ public class WrapperProcessor {
}
}
/**
* 设置节点的bool
*
@ -303,6 +269,7 @@ public class WrapperProcessor {
} else if (MUST_NOT.equals(parentType)) {
bool.mustNot(queryBuilder);
} else {
// just ignore,almost never happen
bool.must(queryBuilder);
}
}
@ -314,28 +281,29 @@ public class WrapperProcessor {
* @param builder 新的根bool
* @return 子节点bool合集, 统一封装至入参builder中
*/
private static BoolQueryBuilder getBool(List<Param> paramList, BoolQueryBuilder builder) {
private static BoolQueryBuilder getBool(List<Param> paramList, BoolQueryBuilder builder, EntityInfo entityInfo, String path) {
if (CollectionUtils.isEmpty(paramList)) {
return builder;
}
paramList.forEach(param -> initBool(builder, param));
return builder;
}
/**
* 获取字段最终名称
*
* @param origin 初始值
* @param condition 是否拼接
* @return 最终字段名
*/
private static String getFinalField(String origin, boolean condition) {
if (condition && origin != null) {
if (!origin.endsWith(KEYWORD_SUFFIX)) {
return origin + KEYWORD_SUFFIX;
}
// 获取字段名称映射关系以及字段类型映射关系
Map<String, String> mappingColumnMap;
Map<String, String> fieldTypeMap;
if (StringUtils.isNotBlank(path)) {
// 嵌套类型
Class<?> clazz = entityInfo.getPathClassMap().get(path);
mappingColumnMap = Optional.ofNullable(entityInfo.getNestedClassMappingColumnMap().get(clazz))
.orElse(new HashMap<>(0));
fieldTypeMap = Optional.ofNullable(entityInfo.getNestedClassFieldTypeMap().get(clazz))
.orElse(new HashMap<>(0));
} else {
mappingColumnMap = entityInfo.getMappingColumnMap();
fieldTypeMap = entityInfo.getFieldTypeMap();
}
return origin;
// 批量初始化每一个参数至BoolQueryBuilder
paramList.forEach(param -> initBool(builder, param, entityInfo, mappingColumnMap, fieldTypeMap));
return builder;
}
@ -405,10 +373,10 @@ public class WrapperProcessor {
if (ArrayUtils.isEmpty(wrapper.include) && ArrayUtils.isEmpty(wrapper.exclude)) {
return;
}
// 获取配置
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
String[] includes = FieldUtils.getRealFields(wrapper.include, mappingColumnMap, dbConfig);
String[] excludes = FieldUtils.getRealFields(wrapper.exclude, mappingColumnMap, dbConfig);
// 获取实际字段
String[] includes = FieldUtils.getRealFields(wrapper.include, mappingColumnMap);
String[] excludes = FieldUtils.getRealFields(wrapper.exclude, mappingColumnMap);
searchSourceBuilder.fetchSource(includes, excludes);
}
@ -450,15 +418,12 @@ public class WrapperProcessor {
* @param searchSourceBuilder 查询参数建造者
*/
private static void setSort(Wrapper<?> wrapper, Map<String, String> mappingColumnMap, SearchSourceBuilder searchSourceBuilder) {
// 获取配置
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
// 批量设置排序字段
if (CollectionUtils.isNotEmpty(wrapper.baseSortParams)) {
wrapper.baseSortParams.forEach(baseSortParam -> {
// 获取es中的实际字段 有可能已经被用户自定义或者驼峰转成下划线
String realField = Objects.isNull(baseSortParam.getSortField()) ?
null : FieldUtils.getRealField(baseSortParam.getSortField(), mappingColumnMap, dbConfig);
null : getRealField(baseSortParam.getSortField(), mappingColumnMap);
SortBuilder<?> sortBuilder = getSortBuilder(realField, baseSortParam);
Optional.ofNullable(sortBuilder).ifPresent(searchSourceBuilder::sort);
});
@ -518,13 +483,10 @@ public class WrapperProcessor {
*/
private static void setAggregations(Wrapper<?> wrapper, Map<String, String> mappingColumnMap,
SearchSourceBuilder searchSourceBuilder) {
// 获取配置
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
// 设置折叠(去重)字段
Optional.ofNullable(wrapper.distinctField)
.ifPresent(distinctField -> {
String realField = FieldUtils.getRealField(distinctField, mappingColumnMap, dbConfig);
String realField = getRealField(distinctField, mappingColumnMap);
searchSourceBuilder.collapse(new CollapseBuilder(realField));
searchSourceBuilder.aggregation(AggregationBuilders.cardinality(REPEAT_NUM_KEY).field(realField));
});
@ -539,7 +501,7 @@ public class WrapperProcessor {
AggregationBuilder root = null;
AggregationBuilder cursor = null;
for (AggregationParam aggParam : aggregationParamList) {
String realField = FieldUtils.getRealField(aggParam.getField(), mappingColumnMap, dbConfig);
String realField = getRealField(aggParam.getField(), mappingColumnMap);
AggregationBuilder builder = getRealAggregationBuilder(aggParam.getAggregationType(), aggParam.getName(), realField);
if (aggParam.isEnablePipeline()) {
// 管道聚合, 构造聚合树

View File

@ -315,12 +315,14 @@ public class EntityInfoHelper {
}
// 其它
FieldType fieldType = FieldType.getByType(IndexUtils.getEsFieldType(tableField.fieldType(), field.getType().getSimpleName()));
entityFieldInfo.setMappingColumn(mappingColumn);
entityFieldInfo.setAnalyzer(tableField.analyzer());
entityFieldInfo.setSearchAnalyzer(tableField.searchAnalyzer());
entityFieldInfo.setFieldType(tableField.fieldType());
entityFieldInfo.setFieldType(fieldType);
entityFieldInfo.setFieldData(tableField.fieldData());
entityFieldInfo.setColumnType(field.getType().getSimpleName());
entityInfo.getFieldTypeMap().putIfAbsent(field.getName(), fieldType.getType());
// 父子类型
if (FieldType.JOIN.equals(tableField.fieldType())) {
@ -389,18 +391,22 @@ public class EntityInfoHelper {
List<Field> allFields = getAllFields(nestedClass);
Map<String, String> mappingColumnMap = new HashMap<>(allFields.size());
Map<String, String> columnMappingMap = new HashMap<>(allFields.size());
Map<String, String> fieldTypeMap = new HashMap<>();
List<EntityFieldInfo> entityFieldInfoList = new ArrayList<>();
Set<String> notSerializedFields = new HashSet<>();
allFields.forEach(field -> {
String mappingColumn;
FieldType fieldType;
// 处理TableField注解
IndexField tableField = field.getAnnotation(IndexField.class);
if (Objects.isNull(tableField)) {
mappingColumn = getMappingColumn(dbConfig, field);
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field);
entityFieldInfo.setMappingColumn(mappingColumn);
entityFieldInfo.setFieldType(FieldType.TEXT);
entityFieldInfo.setColumnType(FieldType.TEXT.getType());
fieldType = FieldType.getByType(IndexUtils.getEsFieldType(FieldType.NONE, field.getType().getSimpleName()));
entityFieldInfo.setFieldType(fieldType);
entityFieldInfo.setColumnType(field.getType().getSimpleName());
entityFieldInfoList.add(entityFieldInfo);
} else {
if (tableField.exist()) {
@ -419,7 +425,7 @@ public class EntityInfoHelper {
// 设置实体字段信息
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field, tableField);
FieldType fieldType = FieldType.NONE.equals(tableField.fieldType()) ? FieldType.KEYWORD : tableField.fieldType();
fieldType = FieldType.NONE.equals(tableField.fieldType()) ? FieldType.KEYWORD_TEXT : tableField.fieldType();
entityFieldInfo.setMappingColumn(mappingColumn);
entityFieldInfo.setFieldType(fieldType);
entityFieldInfo.setFieldData(tableField.fieldData());
@ -432,18 +438,20 @@ public class EntityInfoHelper {
entityFieldInfoList.add(entityFieldInfo);
} else {
mappingColumn = getMappingColumn(dbConfig, field);
fieldType = FieldType.KEYWORD_TEXT;
notSerializedFields.add(field.getName());
}
}
columnMappingMap.putIfAbsent(mappingColumn, field.getName());
mappingColumnMap.putIfAbsent(field.getName(), mappingColumn);
fieldTypeMap.putIfAbsent(field.getName(), fieldType.getType());
});
entityInfo.getNestedNotSerializeField().putIfAbsent(nestedClass, notSerializedFields);
entityInfo.getNestedClassColumnMappingMap().putIfAbsent(nestedClass, columnMappingMap);
entityInfo.getNestedClassMappingColumnMap().putIfAbsent(nestedClass, mappingColumnMap);
entityInfo.getNestedClassFieldTypeMap().putIfAbsent(nestedClass, fieldTypeMap);
entityInfo.getNestedFieldListMap().put(nestedClass, entityFieldInfoList);
}
@ -466,6 +474,8 @@ public class EntityInfoHelper {
// 初始化
String mappingColumn = initMappingColumnMapAndGet(dbConfig, entityInfo, field);
entityFieldInfo.setMappingColumn(mappingColumn);
FieldType fieldType = FieldType.getByType(IndexUtils.getEsFieldType(FieldType.NONE, field.getType().getSimpleName()));
entityInfo.getFieldTypeMap().putIfAbsent(field.getName(), fieldType.getType());
entityFieldInfo.setColumnType(field.getType().getSimpleName());
fieldList.add(entityFieldInfo);
}
@ -588,6 +598,9 @@ public class EntityInfoHelper {
} else {
indexName = tableName;
}
if (StringUtils.isNotBlank(table.routing())) {
entityInfo.setRouting(table.routing());
}
entityInfo.setMaxResultWindow(table.maxResultWindow());
entityInfo.setAliasName(table.aliasName());
entityInfo.setShardsNum(table.shardsNum());

View File

@ -1,5 +1,6 @@
package cn.easyes.core.toolkit;
import cn.easyes.annotation.rely.FieldType;
import cn.easyes.common.constants.BaseEsConstants;
import cn.easyes.common.params.SFunction;
import cn.easyes.common.utils.StringUtils;
@ -18,8 +19,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.easyes.common.constants.BaseEsConstants.DEFAULT_ES_ID_NAME;
import static cn.easyes.common.constants.BaseEsConstants.DEFAULT_ID_NAME;
import static cn.easyes.common.constants.BaseEsConstants.*;
/**
* 核心 处理字段名称工具类
@ -165,16 +165,17 @@ public class FieldUtils {
/**
* 获取实际字段名
*
* @param field 原字段名
* @param mappingColumnMap 字段映射关系map
* @param dbConfig 配置
* @param field 原字段名
* @param mappingColumnMap 字段映射关系map
* @param isMapUnderscoreToCamelCase 是否开启下划线自动转驼峰
* @return 实际字段名
*/
public static String getRealField(String field, Map<String, String> mappingColumnMap, GlobalConfig.DbConfig dbConfig) {
public static String getRealField(String field, Map<String, String> mappingColumnMap) {
String customField = mappingColumnMap.get(field);
if (Objects.nonNull(customField)) {
return DEFAULT_ID_NAME.equals(customField) ? DEFAULT_ES_ID_NAME : customField;
} else {
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
if (dbConfig.isMapUnderscoreToCamelCase()) {
return StringUtils.camelToUnderline(field);
} else {
@ -183,21 +184,40 @@ public class FieldUtils {
}
}
/**
* 获取实际字段名 并且根据配置智能追加.keyword后缀
*
* @param field 字段
* @param fieldTypeMap 字段与es字段类型映射
* @param mappingColumnMap 实体字段与es实际字段映射
* @return 最终的字段
*/
public static String getRealFieldAndSuffix(String field, Map<String, String> fieldTypeMap, Map<String, String> mappingColumnMap) {
GlobalConfig.DbConfig dbConfig = GlobalConfigCache.getGlobalConfig().getDbConfig();
String realField = getRealField(field, mappingColumnMap);
String fieldType = fieldTypeMap.get(field);
boolean addSuffix = dbConfig.isSmartAddKeywordSuffix() && FieldType.KEYWORD_TEXT.getType().equals(fieldType);
if (addSuffix) {
return realField + KEYWORD_SUFFIX;
}
return realField;
}
/**
* 获取实际字段名 不转换id
*
* @param field 原字段名
* @param mappingColumnMap 字段映射关系map
* @param dbConfig 配置
* @param field 原字段名
* @param mappingColumnMap 字段映射关系map
* @param isMapUnderscoreToCamelCase 是否开启下划线自动转驼峰
* @return 实际字段名
*/
public static String getRealFieldNotConvertId(String field, Map<String, String> mappingColumnMap, GlobalConfig.DbConfig dbConfig) {
public static String getRealFieldNotConvertId(String field, Map<String, String> mappingColumnMap, boolean isMapUnderscoreToCamelCase) {
String customField = mappingColumnMap.get(field);
if (Objects.nonNull(customField)) {
return customField;
} else {
if (dbConfig.isMapUnderscoreToCamelCase()) {
if (isMapUnderscoreToCamelCase) {
return StringUtils.camelToUnderline(field);
} else {
return field;
@ -210,12 +230,11 @@ public class FieldUtils {
*
* @param fields 原字段名数组
* @param mappingColumnMap 字段映射关系map
* @param dbConfig 配置
* @return 实际字段数组
*/
public static String[] getRealFields(String[] fields, Map<String, String> mappingColumnMap, GlobalConfig.DbConfig dbConfig) {
public static String[] getRealFields(String[] fields, Map<String, String> mappingColumnMap) {
return Arrays.stream(fields)
.map(field -> getRealField(field, mappingColumnMap, dbConfig))
.map(field -> getRealField(field, mappingColumnMap))
.collect(Collectors.toList())
.toArray(new String[]{});
}
@ -228,7 +247,7 @@ public class FieldUtils {
* @return 实际字段数组
*/
public static List<String> getRealFields(List<String> fields, Map<String, String> mappingColumnMap) {
return Arrays.stream(getRealFields(fields.toArray(new String[0]), mappingColumnMap, GlobalConfigCache.getGlobalConfig().getDbConfig()))
return Arrays.stream(getRealFields(fields.toArray(new String[0]), mappingColumnMap))
.collect(Collectors.toList());
}

View File

@ -101,7 +101,6 @@ public class IndexUtils {
*/
public static boolean createIndex(RestHighLevelClient client, EntityInfo entityInfo, CreateIndexParam indexParam) {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexParam.getIndexName());
// 设置settings信息
if (Objects.isNull(indexParam.getSettings())) {
// 分片个副本信息
@ -238,7 +237,8 @@ public class IndexUtils {
reindexRequest.setDestOpType(BaseEsConstants.DEFAULT_DEST_OP_TYPE);
reindexRequest.setConflicts(BaseEsConstants.DEFAULT_CONFLICTS);
reindexRequest.setRefresh(Boolean.TRUE);
reindexRequest.setTimeout(TimeValue.MAX_VALUE);
int reindexTimeOutHours = GlobalConfigCache.getGlobalConfig().getReindexTimeOutHours();
reindexRequest.setTimeout(TimeValue.timeValueHours(reindexTimeOutHours));
try {
BulkByScrollResponse response = client.reindex(reindexRequest, RequestOptions.DEFAULT);
List<BulkItemResponse.Failure> bulkFailures = response.getBulkFailures();

View File

@ -14,7 +14,7 @@ import java.util.List;
**/
@Data
@Accessors(chain = true)
@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, childClass = Comment.class)
@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, childClass = Comment.class,routing = "666")
public class Document {
/**
* es中的唯一id,字段名随便起,我这里演示用esId,你也可以用id(推荐),bizId等.

View File

@ -4,7 +4,6 @@ import cn.easyes.common.constants.BaseEsConstants;
import cn.easyes.core.biz.EsPageInfo;
import cn.easyes.core.biz.OrderByParam;
import cn.easyes.core.biz.SAPageInfo;
import cn.easyes.core.cache.GlobalConfigCache;
import cn.easyes.core.conditions.select.LambdaEsQueryWrapper;
import cn.easyes.core.conditions.update.LambdaEsUpdateWrapper;
import cn.easyes.core.core.EsWrappers;
@ -177,9 +176,7 @@ public class AllTest {
@Order(6)
public void testOne() {
// 链式调用
Document document = EsWrappers.lambdaChainQuery(documentMapper)
.eq(Document::getTitle, "测试文档3")
.one();
Document document = EsWrappers.lambdaChainQuery(documentMapper).eq(Document::getTitle, "测试文档3").one();
Assertions.assertEquals(document.getContent(), "测试文档内容3的内容被修改了");
}
@ -196,8 +193,6 @@ public class AllTest {
public void testSelectBatchIds() {
List<Document> documents = documentMapper.selectBatchIds(Arrays.asList("1", "2"));
Assertions.assertEquals(2, documents.size());
Assertions.assertEquals("1", documents.get(1).getEsId());
Assertions.assertEquals("老汉2", documents.get(0).getCreator());
}
@Test
@ -568,7 +563,7 @@ public class AllTest {
wrapper.orderByDesc(Document::getStarNum);
List<Document> documents = documentMapper.selectList(wrapper);
Assertions.assertEquals("22", documents.get(0).getEsId());
Assertions.assertEquals("1", documents.get(21).getEsId());
Assertions.assertEquals("21", documents.get(1).getEsId());
}
@Test
@ -595,7 +590,7 @@ public class AllTest {
wrapper.orderBy(orderByParams);
List<Document> documents = documentMapper.selectList(wrapper);
Assertions.assertEquals("22", documents.get(0).getEsId());
Assertions.assertEquals("1", documents.get(21).getEsId());
Assertions.assertEquals("21", documents.get(1).getEsId());
}
@Test
@ -657,13 +652,12 @@ public class AllTest {
FieldSortBuilder fieldSortBuilder = SortBuilders.
fieldSort(FieldUtils.getRealField(
FieldUtils.val(Document::getStarNum),
EntityInfoHelper.getEntityInfo(Document.class).getMappingColumnMap(),
GlobalConfigCache.getGlobalConfig().getDbConfig()));
EntityInfoHelper.getEntityInfo(Document.class).getMappingColumnMap()));
fieldSortBuilder.order(SortOrder.DESC);
wrapper.sort(fieldSortBuilder);
List<Document> documents = documentMapper.selectList(wrapper);
Assertions.assertEquals("22", documents.get(0).getEsId());
Assertions.assertEquals("1", documents.get(21).getEsId());
Assertions.assertEquals("21", documents.get(1).getEsId());
}
@Test
@ -852,11 +846,11 @@ public class AllTest {
System.out.println(boolQueryBuilder);
System.out.println("--------------------");
// MP及EE写法
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.eq("business_type", 1)
.and(a -> a.eq("state", 9).or(b -> b.eq("state", 8).eq("bidding_sign", 1))
)
.and(a -> a.eq("state", 9).or(b -> b.eq("state", 8).eq("bidding_sign", 1)))
.or(i -> i.eq("business_type", 2).in("state", 2, 3));
documentMapper.selectList(wrapper);
}

View File

@ -101,12 +101,8 @@ public class NestedTest {
.or()
.nested("users.faqs", w -> w.match("faq_name", "q3"));
List<Document> documents2 = documentMapper.selectList(wrapper2);
System.out.println(documents2);
}
public static void main(String[] args) {
String val = FieldUtils.val(User::getAge);
System.out.println(val);
}
}