新增@MultiIndexField注解及索引创建相关功能;新增自定义ignore_above参数功能

This commit is contained in:
yinlei1006 2023-08-07 20:29:49 +08:00
parent d76e2c9735
commit cd6e71a0c5
17 changed files with 371 additions and 103 deletions

View File

@ -18,10 +18,4 @@
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,7 +1,6 @@
package org.dromara.easyes.annotation;
import org.dromara.easyes.annotation.rely.*;
import java.lang.annotation.ElementType;
@ -80,6 +79,13 @@ public @interface IndexField {
*/
boolean ignoreCase() default false;
/**
* 长度超过ignore_above设置的字符串将不会被索引或存储 keyword_text默认值为256
*
* @return 索引字段最大长度
*/
int ignoreAbove() default -1;
/**
* 默认嵌套类
*

View File

@ -1,7 +1,6 @@
package org.dromara.easyes.annotation;
import org.dromara.easyes.annotation.rely.DefaultChildClass;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -82,6 +81,4 @@ public @interface IndexName {
* @return CRUD作用的路由
*/
String routing() default "";
RefreshPolicy refreshPolicy() default RefreshPolicy.GLOBAL;
}

View File

@ -0,0 +1,48 @@
package org.dromara.easyes.annotation;
import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType;
/**
* 内部字段索引注解
* <p>
*
* @author yinlei
**/
public @interface InnerIndexField {
/**
* 内部字段的前缀,必须指定,否则无存在意义,且不可重名,重名则以首次出现的为准
*
* @return 内部字段的前缀
*/
String suffix();
/**
* 内部字段在es索引中的类型,必须指定,否则无存在意义
*
* @return 类型
*/
FieldType fieldType();
/**
* 内部字段索引文档时用的分词器
*
* @return 分词器
*/
String analyzer() default Analyzer.NONE;
/**
* 内部字段查询分词器
*
* @return 分词器
*/
String searchAnalyzer() default Analyzer.NONE;
/**
* 内部字段长度超过ignore_above设置的字符串将不会被索引或存储 keyword_text默认值为256
*
* @return 索引内部字段最大长度
*/
int ignoreAbove() default -1;
}

View File

@ -0,0 +1,30 @@
package org.dromara.easyes.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 多字段索引注解
* <p>
*
* @author yinlei
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MultiIndexField {
/**
* 主字段信息
*
* @return 主字段信息
*/
IndexField mainIndexField();
/**
* 内部字段信息
*
* @return 内部字段信息
*/
InnerIndexField[] otherIndexFields() default {};
}

View File

@ -29,6 +29,9 @@ public enum FieldType {
BINARY("binary"),
KEYWORD("keyword"),
TEXT("text"),
/**
* This type can not be used for @InnerIndexField
*/
KEYWORD_TEXT("keyword&text"),
WILDCARD("wildcard"),
/**

View File

@ -1,4 +1,4 @@
package org.dromara.easyes.annotation.rely;
package org.dromara.easyes.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -7,17 +7,11 @@ import lombok.Getter;
* 数据刷新策略枚举
* <p>
* Copyright © 2021 xpc1024 All Rights Reserved
*
* @see org.elasticsearch.action.support.WriteRequest.RefreshPolicy
**/
@AllArgsConstructor
public enum RefreshPolicy {
/**
* 使用全局设置: easy-es.global-config.db-config.refresh-policy
*/
GLOBAL(""),
/**
* 不立即刷新 (es默认的数据刷新策略)
* 默认不刷新
*/
NONE("false"),
/**

View File

@ -61,7 +61,26 @@ public class Assert {
}
}
public static void notBlank(String str, String message) {
if (str == null || str.isEmpty() || !containsText(str)) {
throw new IllegalArgumentException(message);
}
}
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; ++i) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
private static boolean isEmpty(Object[] array) {
return array == null || array.length == 0;
}
}

View File

@ -1,16 +1,17 @@
package org.dromara.easyes.core.biz;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.rely.FieldStrategy;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.core.config.GlobalConfig;
import com.alibaba.fastjson.serializer.NameFilter;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.rely.FieldStrategy;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.core.config.GlobalConfig;
import java.lang.reflect.Field;
import java.util.List;
/**
* es实体字段信息
@ -47,6 +48,10 @@ public class EntityFieldInfo {
* 字段是否忽略大小写默认不忽略 为true时则忽略大小写
*/
private boolean ignoreCase;
/**
* 字段最大索引长度
*/
private Integer ignoreAbove;
/**
* 分词器
*/
@ -86,6 +91,11 @@ public class EntityFieldInfo {
private String sqlSelect;
private NameFilter nameFilter;
/**
* 内部字段列表
*/
private List<InnerFieldInfo> innerFieldInfoList;
/**
* 存在 TableField 注解时, 使用的构造函数
*
@ -95,7 +105,6 @@ public class EntityFieldInfo {
*/
public EntityFieldInfo(GlobalConfig.DbConfig dbConfig, Field field, IndexField tableField) {
this.column = field.getName();
// 优先使用单个字段注解否则使用全局配置
if (tableField.strategy() == FieldStrategy.DEFAULT) {
this.fieldStrategy = dbConfig.getFieldStrategy();
@ -115,4 +124,31 @@ public class EntityFieldInfo {
this.column = field.getName();
}
/**
* 内部字段
*/
@Data
public static class InnerFieldInfo {
/**
* 内部字段名
*/
private String column;
/**
* 内部字段类型
*/
private FieldType fieldType;
/**
* 内部字段分词器
*/
private String analyzer;
/**
* 内部字段查询分词器
*/
private String searchAnalyzer;
/**
* 字段最大索引长度
*/
private Integer ignoreAbove;
}
}

View File

@ -8,7 +8,6 @@ import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.serializer.SerializeFilter;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import java.lang.reflect.Field;
import java.util.*;
@ -178,8 +177,6 @@ public class EntityInfo {
*/
private final Map<Class<?>, List<SerializeFilter>> classSimplePropertyPreFilterMap = new HashMap<>();
private RefreshPolicy refreshPolicy;
/**
* 获取需要进行查询的字段列表
*

View File

@ -2,6 +2,8 @@ package org.dromara.easyes.core.biz;
import lombok.Data;
import java.util.List;
/**
* 索引相关参数
* <p>
@ -45,6 +47,10 @@ public class EsIndexParam {
* 字段是否忽略大小写默认不忽略 为true时则忽略大小写
*/
private boolean ignoreCase;
/**
* 字段最大索引长度 默认256
*/
private Integer ignoreAbove;
/**
* 父名称
*/
@ -53,4 +59,35 @@ public class EsIndexParam {
* 子名称
*/
private String childName;
/**
* 内部字段列表
*/
private List<InnerFieldParam> innerFieldParamList;
/**
* 内部段参数
*/
@Data
public static class InnerFieldParam {
/**
* 内部字段名称
*/
private String column;
/**
* 内部字段类型
*/
private String fieldType;
/**
* 内部分词器
*/
private String analyzer;
/**
* 内部查询分词器
*/
private String searchAnalyzer;
/**
* 内部字段最大索引长度
*/
private Integer ignoreAbove;
}
}

View File

@ -5,7 +5,7 @@ import lombok.Data;
import org.dromara.easyes.annotation.rely.FieldStrategy;
import org.dromara.easyes.annotation.rely.IdType;
import org.dromara.easyes.common.enums.ProcessIndexStrategyEnum;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import org.dromara.easyes.common.enums.RefreshPolicy;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import static org.dromara.easyes.common.constants.BaseEsConstants.EMPTY_STR;
@ -79,7 +79,7 @@ public class GlobalConfig {
*/
private boolean enableTrackTotalHits = true;
/**
* data refresh policy 数据刷新策略,es默认的数据刷新策略为NONE
* data refresh policy 数据刷新策略,默认为NONE
*/
private RefreshPolicy refreshPolicy = RefreshPolicy.NONE;
/**

View File

@ -13,7 +13,7 @@ import org.dromara.easyes.annotation.rely.IdType;
import org.dromara.easyes.common.constants.BaseEsConstants;
import org.dromara.easyes.common.enums.EsQueryTypeEnum;
import org.dromara.easyes.common.enums.MethodEnum;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import org.dromara.easyes.common.enums.RefreshPolicy;
import org.dromara.easyes.common.utils.*;
import org.dromara.easyes.core.biz.*;
import org.dromara.easyes.core.cache.BaseCache;
@ -1485,7 +1485,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
&& searchResponse.getShardFailures() != null
&& searchResponse.getShardFailures().length > ZERO) {
String errorMsg = searchResponse.getShardFailures()[0].toString();
throw ExceptionUtils.eee("es响应出错search response failed ,failedShards: " + errorMsg);
throw ExceptionUtils.eee("search response failed ,failedShards: " + errorMsg);
}
}
@ -1495,7 +1495,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
* @return 刷新策略
*/
private String getRefreshPolicy() {
return EntityInfoHelper.getEntityInfo(entityClass).getRefreshPolicy().getValue();
return GlobalConfigCache.getGlobalConfig().getDbConfig().getRefreshPolicy().getValue();
}
/**

View File

@ -8,11 +8,7 @@ import org.dromara.easyes.annotation.*;
import org.dromara.easyes.annotation.rely.DefaultNestedClass;
import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.annotation.rely.IdType;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import org.dromara.easyes.common.utils.ClassUtils;
import org.dromara.easyes.common.utils.FastJsonUtils;
import org.dromara.easyes.common.utils.ReflectionKit;
import org.dromara.easyes.common.utils.StringUtils;
import org.dromara.easyes.common.utils.*;
import org.dromara.easyes.core.biz.EntityFieldInfo;
import org.dromara.easyes.core.biz.EntityInfo;
import org.dromara.easyes.core.biz.HighLightParam;
@ -106,14 +102,14 @@ public class EntityInfoHelper {
List<Field> list = getAllFields(clazz);
// 标记是否读取到主键
boolean isReadPK = false;
// 是否存在 @TableId 注解
boolean existTableId = isExistIndexId(list);
// 是否存在 @IndexId 注解
boolean existsIndexId = isExistIndexId(list);
List<EntityFieldInfo> fieldList = new ArrayList<>();
for (Field field : list) {
// 主键ID 初始化
if (!isReadPK) {
if (existTableId) {
if (existsIndexId) {
isReadPK = initIndexIdWithAnnotation(dbConfig, entityInfo, field);
} else {
isReadPK = initIndexIdWithoutAnnotation(dbConfig, entityInfo, field);
@ -252,8 +248,8 @@ public class EntityInfoHelper {
Field field, EntityInfo entityInfo) {
boolean hasAnnotation = false;
// 初始化封装IndexField注解信息
if (field.isAnnotationPresent(IndexField.class)) {
// 初始化封装IndexField及MultiIndexField注解信息
if (field.isAnnotationPresent(IndexField.class) || field.isAnnotationPresent(MultiIndexField.class)) {
initIndexFieldAnnotation(dbConfig, entityInfo, field, fieldList);
hasAnnotation = true;
}
@ -294,60 +290,73 @@ public class EntityInfoHelper {
*/
private static void initIndexFieldAnnotation(GlobalConfig.DbConfig dbConfig, EntityInfo entityInfo,
Field field, List<EntityFieldInfo> fieldList) {
IndexField tableField = field.getAnnotation(IndexField.class);
if (tableField.exist()) {
MultiIndexField multiIndexField = field.getAnnotation(MultiIndexField.class);
IndexField indexField = Optional.ofNullable(multiIndexField).map(MultiIndexField::mainIndexField)
.orElse(field.getAnnotation(IndexField.class));
if (indexField.exist()) {
// 存在字段处理
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field, tableField);
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field, indexField);
// 自定义字段名及驼峰下划线转换
String mappingColumn;
if (!StringUtils.isBlank(tableField.value().trim())) {
if (!StringUtils.isBlank(indexField.value().trim())) {
// 自定义注解指定的名称优先级最高
entityInfo.getMappingColumnMap().putIfAbsent(field.getName(), tableField.value());
entityInfo.getColumnMappingMap().putIfAbsent(tableField.value(), field.getName());
mappingColumn = tableField.value();
entityInfo.getMappingColumnMap().putIfAbsent(field.getName(), indexField.value());
entityInfo.getColumnMappingMap().putIfAbsent(indexField.value(), field.getName());
mappingColumn = indexField.value();
} else {
// 下划线驼峰
mappingColumn = initMappingColumnMapAndGet(dbConfig, entityInfo, field);
}
// 日期格式化
if (StringUtils.isNotBlank(tableField.dateFormat())) {
entityFieldInfo.setDateFormat(tableField.dateFormat());
if (StringUtils.isNotBlank(indexField.dateFormat())) {
entityFieldInfo.setDateFormat(indexField.dateFormat());
}
// 是否忽略大小写
FieldType fieldType = FieldType.getByType(IndexUtils.getEsFieldType(tableField.fieldType(), field.getType().getSimpleName()));
FieldType fieldType = FieldType.getByType(IndexUtils.getEsFieldType(indexField.fieldType(), field.getType().getSimpleName()));
if (FieldType.KEYWORD.equals(fieldType)) {
// 仅对keyword类型设置,其它类型es不支持
entityFieldInfo.setIgnoreCase(tableField.ignoreCase());
entityFieldInfo.setIgnoreCase(indexField.ignoreCase());
}
// 最大索引长度
if (indexField.ignoreAbove() > ZERO) {
entityFieldInfo.setIgnoreAbove(indexField.ignoreAbove());
}
// 其它
entityFieldInfo.setMappingColumn(mappingColumn);
entityFieldInfo.setAnalyzer(tableField.analyzer());
entityFieldInfo.setSearchAnalyzer(tableField.searchAnalyzer());
entityFieldInfo.setAnalyzer(indexField.analyzer());
entityFieldInfo.setSearchAnalyzer(indexField.searchAnalyzer());
entityFieldInfo.setFieldType(fieldType);
entityFieldInfo.setFieldData(tableField.fieldData());
entityFieldInfo.setFieldData(indexField.fieldData());
entityFieldInfo.setColumnType(field.getType().getSimpleName());
entityInfo.getFieldTypeMap().putIfAbsent(field.getName(), fieldType.getType());
// 父子类型
if (FieldType.JOIN.equals(tableField.fieldType())) {
entityFieldInfo.setParentName(tableField.parentName());
entityFieldInfo.setChildName(tableField.childName());
if (FieldType.JOIN.equals(indexField.fieldType())) {
entityFieldInfo.setParentName(indexField.parentName());
entityFieldInfo.setChildName(indexField.childName());
entityInfo.setJoinFieldName(mappingColumn);
entityInfo.setJoinFieldClass(tableField.joinFieldClass());
entityInfo.getPathClassMap().putIfAbsent(field.getName(), tableField.joinFieldClass());
processNested(tableField.joinFieldClass(), dbConfig, entityInfo);
entityInfo.setJoinFieldClass(indexField.joinFieldClass());
entityInfo.getPathClassMap().putIfAbsent(field.getName(), indexField.joinFieldClass());
processNested(indexField.joinFieldClass(), dbConfig, entityInfo);
}
// 处理内部字段
InnerIndexField[] innerIndexFields = Optional.ofNullable(multiIndexField).map(MultiIndexField::otherIndexFields).orElse(null);
processInnerField(innerIndexFields, entityFieldInfo);
fieldList.add(entityFieldInfo);
// 嵌套类处理
if (DefaultNestedClass.class != tableField.nestedClass()) {
if (DefaultNestedClass.class != indexField.nestedClass()) {
// 嵌套类
entityInfo.getPathClassMap().putIfAbsent(field.getName(), tableField.nestedClass());
processNested(tableField.nestedClass(), dbConfig, entityInfo);
entityInfo.getPathClassMap().putIfAbsent(field.getName(), indexField.nestedClass());
processNested(indexField.nestedClass(), dbConfig, entityInfo);
}
} else {
@ -405,8 +414,10 @@ public class EntityInfoHelper {
String mappingColumn;
FieldType fieldType;
// 处理TableField注解
IndexField tableField = field.getAnnotation(IndexField.class);
if (Objects.isNull(tableField)) {
MultiIndexField multiIndexField = field.getAnnotation(MultiIndexField.class);
IndexField indexField = Optional.ofNullable(multiIndexField).map(MultiIndexField::mainIndexField)
.orElse(field.getAnnotation(IndexField.class));
if (Objects.isNull(indexField)) {
mappingColumn = getMappingColumn(dbConfig, field);
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field);
entityFieldInfo.setMappingColumn(mappingColumn);
@ -415,36 +426,41 @@ public class EntityInfoHelper {
entityFieldInfo.setColumnType(field.getType().getSimpleName());
entityFieldInfoList.add(entityFieldInfo);
} else {
if (tableField.exist()) {
if (indexField.exist()) {
// 子嵌套,递归处理
if (DefaultNestedClass.class != tableField.nestedClass()) {
entityInfo.getPathClassMap().putIfAbsent(field.getName(), tableField.nestedClass());
processNested(tableField.nestedClass(), dbConfig, entityInfo);
if (DefaultNestedClass.class != indexField.nestedClass()) {
entityInfo.getPathClassMap().putIfAbsent(field.getName(), indexField.nestedClass());
processNested(indexField.nestedClass(), dbConfig, entityInfo);
}
// 字段名称
if (StringUtils.isNotBlank(tableField.value().trim())) {
mappingColumn = tableField.value();
if (StringUtils.isNotBlank(indexField.value().trim())) {
mappingColumn = indexField.value();
} else {
mappingColumn = getMappingColumn(dbConfig, field);
}
// 设置实体字段信息
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field, tableField);
fieldType = FieldType.NONE.equals(tableField.fieldType()) ? FieldType.KEYWORD_TEXT : tableField.fieldType();
EntityFieldInfo entityFieldInfo = new EntityFieldInfo(dbConfig, field, indexField);
fieldType = FieldType.NONE.equals(indexField.fieldType()) ? FieldType.KEYWORD_TEXT : indexField.fieldType();
entityFieldInfo.setMappingColumn(mappingColumn);
entityFieldInfo.setFieldType(fieldType);
entityFieldInfo.setFieldData(tableField.fieldData());
entityFieldInfo.setFieldData(indexField.fieldData());
entityFieldInfo.setColumnType(fieldType.getType());
entityFieldInfo.setAnalyzer(tableField.analyzer());
entityFieldInfo.setSearchAnalyzer(tableField.searchAnalyzer());
entityFieldInfo.setAnalyzer(indexField.analyzer());
entityFieldInfo.setSearchAnalyzer(indexField.searchAnalyzer());
if (FieldType.KEYWORD.equals(fieldType)) {
// 仅对keyword类型设置,其它类型es不支持
entityFieldInfo.setIgnoreCase(tableField.ignoreCase());
entityFieldInfo.setIgnoreCase(indexField.ignoreCase());
}
if (StringUtils.isNotBlank(tableField.dateFormat())) {
entityFieldInfo.setDateFormat(tableField.dateFormat());
if (StringUtils.isNotBlank(indexField.dateFormat())) {
entityFieldInfo.setDateFormat(indexField.dateFormat());
}
// 处理内部字段
InnerIndexField[] innerIndexFields = Optional.ofNullable(multiIndexField).map(MultiIndexField::otherIndexFields).orElse(null);
processInnerField(innerIndexFields, entityFieldInfo);
entityFieldInfoList.add(entityFieldInfo);
} else {
mappingColumn = getMappingColumn(dbConfig, field);
@ -464,6 +480,31 @@ public class EntityInfoHelper {
entityInfo.getNestedFieldListMap().put(nestedClass, entityFieldInfoList);
}
/**
* 处理内部字段
*
* @param innerIndexFields 内部字段注解数组
* @param entityFieldInfo 内部字段信息
*/
private static void processInnerField(InnerIndexField[] innerIndexFields, EntityFieldInfo entityFieldInfo) {
if (ArrayUtils.isNotEmpty(innerIndexFields)) {
List<EntityFieldInfo.InnerFieldInfo> innerFieldInfoList = new ArrayList<>();
Arrays.stream(innerIndexFields).forEach(innerField -> {
Assert.notBlank(innerField.suffix(), "The Annotation MultiIndexField.InnerIndexField.value must has text");
EntityFieldInfo.InnerFieldInfo innerFieldInfo = new EntityFieldInfo.InnerFieldInfo();
innerFieldInfo.setColumn(innerField.suffix());
innerFieldInfo.setFieldType(innerField.fieldType());
innerFieldInfo.setAnalyzer(innerField.analyzer());
innerFieldInfo.setSearchAnalyzer(innerField.searchAnalyzer());
if (innerField.ignoreAbove() > 0){
innerFieldInfo.setIgnoreAbove(innerField.ignoreAbove());
}
innerFieldInfoList.add(innerFieldInfo);
});
entityFieldInfo.setInnerFieldInfoList(innerFieldInfoList);
}
}
/**
* 字段属性初始化
@ -617,12 +658,6 @@ public class EntityInfoHelper {
entityInfo.setReplicasNum(table.replicasNum());
entityInfo.setChild(table.child());
entityInfo.setChildClass(table.childClass());
RefreshPolicy refreshPolicy = table.refreshPolicy();
if (RefreshPolicy.GLOBAL.equals(refreshPolicy)) {
refreshPolicy = dbConfig.getRefreshPolicy();
}
entityInfo.setRefreshPolicy(refreshPolicy);
}
String targetIndexName = indexName;

View File

@ -59,20 +59,14 @@ import static org.dromara.easyes.common.constants.BaseEsConstants.*;
public class IndexUtils {
private static final String FIELDS_KEY;
private static final Map<String, Object> FIELDS_MAP;
private static final int IGNORE_ABOVE;
private static final int DEFAULT_IGNORE_ABOVE;
private static final String IGNORE_ABOVE_KEY;
static {
FIELDS_MAP = new HashMap<>();
FIELDS_KEY = "fields";
IGNORE_ABOVE = 256;
DEFAULT_IGNORE_ABOVE = 256;
IGNORE_ABOVE_KEY = "ignore_above";
Map<String, Object> keywordsMap = new HashMap<>();
keywordsMap.put(TYPE, FieldType.KEYWORD.getType());
keywordsMap.put(IGNORE_ABOVE_KEY, IGNORE_ABOVE);
FIELDS_MAP.put(FieldType.KEYWORD.getType(), keywordsMap);
}
/**
@ -323,7 +317,7 @@ public class IndexUtils {
return fieldType.getType();
}
// 否则根据类型推断,String以及找不到的类型一律被当做keyword处理
// 否则根据类型推断,String以及找不到的类型一律被当做keyword_text复核类型处理
JdkDataTypeEnum jdkDataType = JdkDataTypeEnum.getByType(typeName.toLowerCase());
String type;
switch (jdkDataType) {
@ -414,9 +408,17 @@ public class IndexUtils {
}
// 设置type
Map<String, Object> fieldsMap = null;
if (FieldType.KEYWORD_TEXT.getType().equals(indexParam.getFieldType())) {
// 复合类型需特殊处理
info.put(BaseEsConstants.TYPE, FieldType.TEXT.getType());
info.put(FIELDS_KEY, FIELDS_MAP);
fieldsMap = new HashMap<>();
Map<String, Object> keywordMap = new HashMap<>();
keywordMap.put(TYPE, FieldType.KEYWORD.getType());
int ignoreAbove = Optional.ofNullable(indexParam.getIgnoreAbove()).orElse(DEFAULT_IGNORE_ABOVE);
keywordMap.put(IGNORE_ABOVE_KEY, ignoreAbove);
fieldsMap.put(FieldType.KEYWORD.getType(), keywordMap);
info.put(FIELDS_KEY, fieldsMap);
} else {
info.put(BaseEsConstants.TYPE, indexParam.getFieldType());
}
@ -427,11 +429,10 @@ public class IndexUtils {
if (containsTextType) {
// 设置分词器
Optional.ofNullable(indexParam.getAnalyzer())
.ifPresent(analyzer ->
info.put(BaseEsConstants.ANALYZER, indexParam.getAnalyzer().toLowerCase()));
.ifPresent(analyzer -> info.put(BaseEsConstants.ANALYZER, analyzer.toLowerCase()));
Optional.ofNullable(indexParam.getSearchAnalyzer())
.ifPresent(searchAnalyzer ->
info.put(BaseEsConstants.SEARCH_ANALYZER, indexParam.getSearchAnalyzer().toLowerCase()));
info.put(BaseEsConstants.SEARCH_ANALYZER, searchAnalyzer.toLowerCase()));
// 设置是否对text类型进行聚合处理
MyOptional.ofNullable(indexParam.getFieldData()).ifTrue(fieldData -> info.put(FIELD_DATA, fieldData));
@ -462,6 +463,31 @@ public class IndexUtils {
if (dbConfig.isMapUnderscoreToCamelCase()) {
fieldName = StringUtils.camelToUnderline(fieldName);
}
// 设置内部字段
if (CollectionUtils.isNotEmpty(indexParam.getInnerFieldParamList())) {
Map<String, Object> finalFieldsMap = Optional.ofNullable(fieldsMap).orElseGet(HashMap::new);
indexParam.getInnerFieldParamList().forEach(innerFieldParam -> {
Map<String, Object> innerInfo = new HashMap<>();
if (FieldType.KEYWORD_TEXT.getType().equals(innerFieldParam.getFieldType())) {
ExceptionUtils.eee("The fieldType FieldType.KEYWORD_TEXT just for mainIndexField, can not be used in @InnerIndexField");
}
innerInfo.put(TYPE, innerFieldParam.getFieldType());
boolean innerContainsTextType = FieldType.TEXT.getType().equals(innerFieldParam.getFieldType()) ||
FieldType.KEYWORD_TEXT.getType().equals(innerFieldParam.getFieldType());
if (innerContainsTextType) {
Optional.ofNullable(innerFieldParam.getAnalyzer()).ifPresent(i -> innerInfo.put(ANALYZER, i));
Optional.ofNullable(innerFieldParam.getSearchAnalyzer())
.ifPresent(i -> innerInfo.put(SEARCH_ANALYZER, i));
}
Optional.ofNullable(innerFieldParam.getIgnoreAbove())
.ifPresent(i -> innerInfo.put(IGNORE_ABOVE_KEY, innerFieldParam.getIgnoreAbove()));
finalFieldsMap.putIfAbsent(innerFieldParam.getColumn(), innerInfo);
});
info.put(FIELDS_KEY, finalFieldsMap);
}
properties.put(fieldName, info);
});
return properties;
@ -589,6 +615,25 @@ public class IndexUtils {
esIndexParam.setIgnoreCase(field.isIgnoreCase());
Optional.ofNullable(field.getParentName()).ifPresent(esIndexParam::setParentName);
Optional.ofNullable(field.getChildName()).ifPresent(esIndexParam::setChildName);
// 内部字段处理
final List<EntityFieldInfo.InnerFieldInfo> innerFieldInfoList = field.getInnerFieldInfoList();
if (CollectionUtils.isNotEmpty(innerFieldInfoList)) {
List<EsIndexParam.InnerFieldParam> innerFieldParamList = new ArrayList<>();
innerFieldInfoList.forEach(innerFieldInfo -> {
EsIndexParam.InnerFieldParam innerFieldParam = new EsIndexParam.InnerFieldParam();
innerFieldParam.setColumn(innerFieldInfo.getColumn());
if (!Analyzer.NONE.equals(innerFieldInfo.getAnalyzer())) {
innerFieldParam.setAnalyzer(innerFieldInfo.getAnalyzer());
}
if (!Analyzer.NONE.equals(innerFieldInfo.getSearchAnalyzer())) {
innerFieldParam.setSearchAnalyzer(innerFieldInfo.getSearchAnalyzer());
}
innerFieldParam.setFieldType(innerFieldInfo.getFieldType().getType());
innerFieldParamList.add(innerFieldParam);
});
esIndexParam.setInnerFieldParamList(innerFieldParamList);
}
esIndexParamList.add(esIndexParam);
});
}

View File

@ -5,7 +5,6 @@ import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.easyes.annotation.*;
import org.dromara.easyes.annotation.rely.*;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import java.util.List;
@ -16,9 +15,7 @@ import java.util.List;
**/
@Data
@Accessors(chain = true)
@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2,
keepGlobalPrefix = true, childClass = Comment.class, routing = "testRouting",
refreshPolicy = RefreshPolicy.IMMEDIATE)
@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, childClass = Comment.class, routing = "testRouting")
public class Document {
/**
* es中的唯一id,字段名随便起,我这里演示用esId,你也可以用id(推荐),bizId等.
@ -126,4 +123,16 @@ public class Document {
*/
@Distance(decimalPlaces = 2)
private Double distance2;
/**
* 复合字段,此注解和SpringData中的MultiField用法类似 适用于对同一个字段通过多种分词器检索的场景
*/
@MultiIndexField(mainIndexField = @IndexField(fieldType = FieldType.KEYWORD),
otherIndexFields = {@InnerIndexField(suffix = "zh", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART),
@InnerIndexField(suffix = "pinyin", fieldType = FieldType.TEXT, analyzer = "pinyin")})
private String multiField;
/**
* 英文名
*/
private String english;
}

View File

@ -85,6 +85,8 @@ public class AllTest {
Rectangle rectangle = new Rectangle(39.084509D, 41.187328D, 70.610461D, 20.498353D);
document.setGeoLocation(rectangle.toString());
document.setStarNum(1);
document.setMultiField("葡萄糖酸钙口服溶液");
document.setEnglish("Calcium Gluconate");
int successCount = documentMapper.insert(document);
Assertions.assertEquals(successCount, 1);
@ -880,6 +882,21 @@ public class AllTest {
Assertions.assertEquals(22, documents.size());
}
@Test
@Order(6)
public void testMultiFieldSelect() {
// 药品 中文名叫葡萄糖酸钙口服溶液 英文名叫 Calcium Gluconate 汉语拼音为 putaotangsuangaikoufurongye
// 用户可以通过模糊检索,例如输入 Calcium 葡萄糖 putaotang时对应药品均可以被检索到
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.match("english", "Calcium")
.or()
.match("multi_field.zh", "葡萄糖")
.or()
.match("multi_field.pinyin", "putaotang");
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
// 4.删除
@Test
@Order(7)
@ -939,4 +956,5 @@ public class AllTest {
documentMapper.selectList(wrapper);
}
}