v2.0.0-beta5

1.嵌套类型支持高亮注解
2.增加小黑子趣味debug模式
3.修复已知缺陷
4.持续更新中...
This commit is contained in:
邢鹏成 2023-10-30 22:20:47 +08:00
parent db8c94495e
commit 095a7bb2b2
24 changed files with 407 additions and 94 deletions

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<relativePath>../easy-es-parent</relativePath> <relativePath>../easy-es-parent</relativePath>
</parent> </parent>

View File

@ -9,7 +9,7 @@ import java.util.Arrays;
**/ **/
public enum FieldType { public enum FieldType {
/** /**
* none Required inside the framework, do not use 框架内部需要,切勿使用,若不慎使用则会被当做keyword&text类型 * none Required inside the framework, do not use 框架内部需要,切勿使用,若不慎使用则会被当做keyword_text类型
*/ */
NONE("none"), NONE("none"),
/** /**

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<relativePath>../easy-es-parent</relativePath> <relativePath>../easy-es-parent</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -18,8 +18,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.dromara.easyes.common.constants.BaseEsConstants.ENABLE_BANNER; import static org.dromara.easyes.common.constants.BaseEsConstants.*;
import static org.dromara.easyes.common.constants.BaseEsConstants.ENABLE_PREFIX;
/** /**
* 注册bean * 注册bean
@ -46,19 +45,50 @@ public class MapperScannerRegister implements ImportBeanDefinitionRegistrar, Res
//打印banner @author dazer007 //打印banner @author dazer007
boolean banner = Optional.ofNullable(environment.getProperty(ENABLE_BANNER)).map(Boolean::parseBoolean).orElse(Boolean.TRUE); boolean banner = Optional.ofNullable(environment.getProperty(ENABLE_BANNER)).map(Boolean::parseBoolean).orElse(Boolean.TRUE);
if (banner) { if (banner) {
boolean iKunMode = Optional.ofNullable(environment.getProperty(ENABLE_I_KUN_MODE)).map(Boolean::parseBoolean).orElse(Boolean.FALSE);
String versionStr = EEVersionUtils.getJarVersion(this.getClass()); String versionStr = EEVersionUtils.getJarVersion(this.getClass());
System.out.println("\n" + String wechatStr = ":: wechat :: 252645816, add and become muscle man! >";
"___ _ _ ___\n" + if (iKunMode) {
" | __| __ _ ___ | || | ___ | __| ___\n" + System.out.println(" 鸡你太美\n" +
" | _| / _` | (_-< \\_, | |___| | _| (_-<\n" + " 鸡你实在太美\n" +
" |___| \\__,_| /__/_ _|__/ _____ |___| /__/_\n" + " 鸡你是太美\n" +
"_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"|_| \"\"\"\"|_| |_|\"\"\"\"\"|_|\"\"\"\"\"|\n" + " 鸡你太美\n" +
"\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\n" + " 实在是太美鸡你\n" +
"------------------------------------------------------>" " 鸡你 实在是太美鸡你 美\n" +
); " 鸡你 实在是太美鸡美 太美\n" +
" 鸡你 实在是太美鸡美 太美\n" +
" 鸡你 实在是太美鸡美 太美\n" +
" 鸡你 鸡你实在是美太美 美蓝球球球\n" +
"鸡 鸡 鸡你实在是太美 篮球篮球球球球\n" +
" 鸡 鸡你太美裆鸡太啊 球球蓝篮球球\n" +
" 鸡你太美裆裆鸡美 球球球\n" +
" 鸡你裆小 j 鸡太美\n" +
" 鸡太美 鸡太美\n" +
" 鸡美 鸡美\n" +
" 鸡美 鸡美\n" +
" 鸡美 鸡美\n" +
" 鸡太 鸡太\n" +
" 鸡 脚 鸡脚\n" +
" 皮 鞋 皮鞋金猴\n" +
" 金光 金光 大道\n" +
" 大道\n" +
" 鸡神保佑 永不宕机 永无BUG");
wechatStr = ":: wechat :: 252645816, add and join ikun(小黑子) group! >";
} else {
System.out.println("\n" +
"___ _ _ ___\n" +
" | __| __ _ ___ | || | ___ | __| ___\n" +
" | _| / _` | (_-< \\_, | |___| | _| (_-<\n" +
" |___| \\__,_| /__/_ _|__/ _____ |___| /__/_\n" +
"_|\"\"\"\"\"|_|\"\"\"\"\"|_|\"\"\"\"\"|_| \"\"\"\"|_| |_|\"\"\"\"\"|_|\"\"\"\"\"|\n" +
"\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\"`-0-0-'\n" +
"----------------------------------------------------------->"
);
}
// 版本长度并不固定,比如beta版,所以需要特殊处理 // 版本长度并不固定,比如beta版,所以需要特殊处理
int width = 38; int width = 43;
int blank = width - versionStr.length(); int blank = width - versionStr.length();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(":: version :: ") sb.append(":: version :: ")
@ -67,11 +97,15 @@ public class MapperScannerRegister implements ImportBeanDefinitionRegistrar, Res
sb.append(" "); sb.append(" ");
} }
sb.append(">"); sb.append(">");
if (iKunMode) {
System.out.println("----------------------------------------------------------->");
}
System.out.println(":: project :: Easy-Es >");
System.out.println(sb); System.out.println(sb);
System.out.println(":: home :: https://easy-es.cn/ >"); System.out.println(":: home :: https://easy-es.cn/ >");
System.out.println(":: community :: https://dromara.org/ >"); System.out.println(":: community :: https://dromara.org/ >");
System.out.println(":: wechat :: 252645816, add and become muscle man! >"); System.out.println(wechatStr);
System.out.println("------------------------------------------------------>"); System.out.println("----------------------------------------------------------->");
} }
AnnotationAttributes mapperScanAttrs = AnnotationAttributes AnnotationAttributes mapperScanAttrs = AnnotationAttributes

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<relativePath>../easy-es-parent</relativePath> <relativePath>../easy-es-parent</relativePath>
</parent> </parent>

View File

@ -14,6 +14,10 @@ public interface BaseEsConstants {
* 是否打印本框架Banner * 是否打印本框架Banner
*/ */
String ENABLE_BANNER = "easy-es.banner"; String ENABLE_BANNER = "easy-es.banner";
/**
* 是否开启iKun模式
*/
String ENABLE_I_KUN_MODE = "easy-es.global-config.i-kun-mode";
/** /**
* 默认主键名称 * 默认主键名称
*/ */
@ -139,6 +143,10 @@ public interface BaseEsConstants {
* DSL语句前缀 * DSL语句前缀
*/ */
String DSL_PREFIX = "===> Execute By Easy-Es: "; String DSL_PREFIX = "===> Execute By Easy-Es: ";
/**
* DSL语句
*/
String I_KUN_PREFIX = "===> 鸡你太美提醒您, 以下内容由Easy-Es执行:";
/** /**
* count DSL语句前缀 * count DSL语句前缀
*/ */
@ -249,4 +257,12 @@ public interface BaseEsConstants {
* 缩放因子索引字段名称 * 缩放因子索引字段名称
*/ */
String SCALING_FACTOR_FIELD = "scaling_factor"; String SCALING_FACTOR_FIELD = "scaling_factor";
/**
* path分隔符
*/
String SIGN = "\\.";
/**
* path分隔符 不转义
*/
String STR_SIGN = ".";
} }

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<relativePath>../easy-es-parent</relativePath> <relativePath>../easy-es-parent</relativePath>
</parent> </parent>

View File

@ -1,14 +1,14 @@
package org.dromara.easyes.core.biz; package org.dromara.easyes.core.biz;
import org.dromara.easyes.annotation.rely.IdType;
import org.dromara.easyes.annotation.rely.JoinField;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import org.dromara.easyes.common.constants.BaseEsConstants;
import com.alibaba.fastjson.PropertyNamingStrategy; import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.serializer.SerializeFilter; import com.alibaba.fastjson.serializer.SerializeFilter;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.dromara.easyes.annotation.rely.IdType;
import org.dromara.easyes.annotation.rely.JoinField;
import org.dromara.easyes.annotation.rely.RefreshPolicy;
import org.dromara.easyes.common.constants.BaseEsConstants;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.*; import java.util.*;
@ -124,7 +124,11 @@ public class EntityInfo {
/** /**
* 当前主类的高亮字段列表 * 当前主类的高亮字段列表
*/ */
private List<HighLightParam> highLightParams = new ArrayList<>(); private List<HighLightParam> highlightParams = new ArrayList<>();
/**
* 嵌套类-高亮字段列表
*/
private Map<Class<?>, List<HighLightParam>> nestedHighLightParamsMap = new HashMap<>();
/** /**
* fastjson 字段命名策略 * fastjson 字段命名策略
*/ */
@ -137,6 +141,10 @@ public class EntityInfo {
* 实体字段->高亮返回结果 键值对 * 实体字段->高亮返回结果 键值对
*/ */
private final Map<String, String> highlightFieldMap = new HashMap<>(); private final Map<String, String> highlightFieldMap = new HashMap<>();
/**
* 嵌套类 实体字段->高亮返回结果字段
*/
private final Map<Class<?>, Map<String, String>> nestedHighlightFieldMap = new HashMap<>();
/** /**
* 实体字段名->es字段类型 * 实体字段名->es字段类型
*/ */
@ -182,6 +190,7 @@ public class EntityInfo {
* 数据刷新策略 * 数据刷新策略
*/ */
private RefreshPolicy refreshPolicy; private RefreshPolicy refreshPolicy;
/** /**
* 获取需要进行查询的字段列表 * 获取需要进行查询的字段列表
* *

View File

@ -21,6 +21,10 @@ public class GlobalConfig {
* whether to print dsl log 是否打印执行的dsl语句 * whether to print dsl log 是否打印执行的dsl语句
*/ */
private boolean printDsl = true; private boolean printDsl = true;
/**
* for fun, whether to print love chinese "kung fu" mode 是否开启爱坤(小黑子)模式 开启后日志将进入疯狂状态, 后期也会在此特殊模式下提供更多趣味化及傻瓜功能 让编码不仅简单,还有趣!
*/
private boolean iKunMode;
/** /**
* process index mode Manual by default 索引处理模式 默认开启手动模式 * process index mode Manual by default 索引处理模式 默认开启手动模式
*/ */

View File

@ -18,6 +18,7 @@ import org.dromara.easyes.common.utils.*;
import org.dromara.easyes.core.biz.*; import org.dromara.easyes.core.biz.*;
import org.dromara.easyes.core.cache.BaseCache; import org.dromara.easyes.core.cache.BaseCache;
import org.dromara.easyes.core.cache.GlobalConfigCache; import org.dromara.easyes.core.cache.GlobalConfigCache;
import org.dromara.easyes.core.config.GlobalConfig;
import org.dromara.easyes.core.toolkit.EntityInfoHelper; import org.dromara.easyes.core.toolkit.EntityInfoHelper;
import org.dromara.easyes.core.toolkit.FieldUtils; import org.dromara.easyes.core.toolkit.FieldUtils;
import org.dromara.easyes.core.toolkit.IndexUtils; import org.dromara.easyes.core.toolkit.IndexUtils;
@ -1053,8 +1054,8 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
// 解析json // 解析json
T entity = JSON.parseObject(searchHit.getSourceAsString(), entityClass, entityInfo.getExtraProcessor()); T entity = JSON.parseObject(searchHit.getSourceAsString(), entityClass, entityInfo.getExtraProcessor());
// 高亮字段处理 // 主类中高亮字段处理
if (CollectionUtils.isNotEmpty(entityInfo.getHighLightParams())) { if (CollectionUtils.isNotEmpty(entityInfo.getHighlightParams())) {
Map<String, String> highlightFieldMap = getHighlightFieldMap(); Map<String, String> highlightFieldMap = getHighlightFieldMap();
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
highlightFields.forEach((key, value) -> { highlightFields.forEach((key, value) -> {
@ -1063,6 +1064,9 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
}); });
} }
// 嵌套类中的高亮处理
setInnerHighlight(searchHit, entity, entityInfo.getNestedHighlightFieldMap());
// 得分字段处理 // 得分字段处理
setScore(entity, searchHit.getScore(), entityInfo); setScore(entity, searchHit.getScore(), entityInfo);
@ -1078,6 +1082,97 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
return entity; return entity;
} }
/**
* 设置嵌套类型中的高亮
*
* @param searchHit 查询结果
* @param root 主实体对象
* @param nestedHighlightFieldMap 字段缓存
*/
private void setInnerHighlight(SearchHit searchHit, T root, Map<Class<?>, Map<String, String>> nestedHighlightFieldMap) {
// 遍历innerHits 批量设置
if (CollectionUtils.isEmpty(searchHit.getInnerHits())) {
return;
}
searchHit.getInnerHits()
.forEach((k, v) -> {
SearchHit[] hits = v.getHits();
Arrays.stream(hits).forEach(hit -> {
SearchHit.NestedIdentity nestedIdentity = hit.getNestedIdentity();
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (CollectionUtils.isNotEmpty(highlightFields) && nestedIdentity != null) {
highlightFields.forEach((k1, v1) -> {
String highLightContent = Arrays.stream(v1.getFragments()).map(Text::string).collect(Collectors.joining());
String[] split = k1.split(SIGN);
String highLightField = split[split.length - 1];
processInnerHighlight(nestedIdentity.getField().string(), root, nestedIdentity,
highLightField, highLightContent, nestedHighlightFieldMap);
});
}
});
});
}
/**
* 递归处理嵌套类中的高亮
*
* @param path 嵌套类路径
* @param root
* @param nestedIdentity 嵌套路径
* @param highlightField 高亮字段
* @param highlightContent 高亮内容
* @param nestedHighlightFieldMap 字段缓存
*/
private void processInnerHighlight(String path, Object root, SearchHit.NestedIdentity nestedIdentity, String highlightField,
String highlightContent, Map<Class<?>, Map<String, String>> nestedHighlightFieldMap) {
// 反射, 获取嵌套对象
Method method = BaseCache.getterMethod(root.getClass(), nestedIdentity.getField().string());
Object invoke = null;
try {
invoke = method.invoke(root);
} catch (Throwable e) {
e.printStackTrace();
LogUtils.error("processInnerHighlight invoke error, class:%s,methodName:%s",
root.getClass().getSimpleName(), nestedIdentity.getField().string());
}
// 嵌套对象为容器的情况
if (invoke instanceof Collection) {
Collection<?> coll = (Collection<?>) invoke;
Iterator<?> iterator = coll.iterator();
int i = 0;
while (iterator.hasNext()) {
Object next = iterator.next();
// 不在nestedIdentity中的项无需处理
if (i == nestedIdentity.getOffset()) {
if (path.equals(nestedIdentity.getField().string())) {
final SearchHit.NestedIdentity child = nestedIdentity.getChild();
if (child != null) {
// 递归 对子项执行相同操作
processInnerHighlight(child.getField().string(), next, child, highlightField, highlightContent, nestedHighlightFieldMap);
} else {
// 已找到需要被高亮的叶子节点
String realHighlightField = Optional.ofNullable(nestedHighlightFieldMap.get(next.getClass()))
.map(highlightFieldMap -> highlightFieldMap.get(highlightField)).orElse(highlightField);
setHighlightValue(next, realHighlightField, highlightContent);
}
}
}
i++;
}
} else {
// 不太可能发生, 因为非容器的嵌套类型无意义,可以直接大宽表,但考虑到健壮性,仍针对个别傻狍子用户兼容处理
Object finalInvoke = invoke;
Optional.ofNullable(finalInvoke).ifPresent(i -> {
String realHighlightField = Optional.ofNullable(nestedHighlightFieldMap.get(finalInvoke.getClass()))
.map(highlightFieldMap -> highlightFieldMap.get(highlightField)).orElse(highlightField);
setHighlightValue(i, realHighlightField, highlightContent);
});
}
}
/** /**
* 设置距离 * 设置距离
* *
@ -1395,9 +1490,9 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
* @param highlightField 高亮返回字段 * @param highlightField 高亮返回字段
* @param value 高亮结果值 * @param value 高亮结果值
*/ */
private void setHighlightValue(T entity, String highlightField, String value) { private void setHighlightValue(Object entity, String highlightField, String value) {
try { try {
Method invokeMethod = BaseCache.setterMethod(entityClass, highlightField); Method invokeMethod = BaseCache.setterMethod(entity.getClass(), highlightField);
invokeMethod.invoke(entity, value); invokeMethod.invoke(entity, value);
} catch (Throwable e) { } catch (Throwable e) {
LogUtils.formatError("setHighlightValue error,entity:%s,highlightField:%s,value:%s,e:%s", LogUtils.formatError("setHighlightValue error,entity:%s,highlightField:%s,value:%s,e:%s",
@ -1450,12 +1545,18 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
* @param countRequest 统计数量查询参数 * @param countRequest 统计数量查询参数
*/ */
private void printCountDSL(CountRequest countRequest) { private void printCountDSL(CountRequest countRequest) {
if (GlobalConfigCache.getGlobalConfig().isPrintDsl() && Objects.nonNull(countRequest)) { // GlobalConfig globalConfig = GlobalConfigCache.getGlobalConfig();
Optional.ofNullable(countRequest.query()) // if (.isPrintDsl() && Objects.nonNull(countRequest)){
.ifPresent(source -> LogUtils.info(BaseEsConstants.COUNT_DSL_PREFIX // Optional.ofNullable(countRequest.query())
+ "\nindex-name: " + org.springframework.util.StringUtils.arrayToCommaDelimitedString(countRequest.indices()) // .ifPresent(source -> {
+ "\nDSL" + source)); // String prefix = globalConfig.isIKunMode() ? I_KUN_PREFIX : DSL_PREFIX;
} // LogUtils.info(BaseEsConstants.COUNT_DSL_PREFIX
// + "\nindex-name: " + org.springframework.util.StringUtils.arrayToCommaDelimitedString(countRequest.indices())
// + "\nDSL" + source)
// });
// }
Optional.ofNullable(countRequest.query())
.ifPresent(i -> doPrint(i.toString(), countRequest.indices()));
} }
/** /**
@ -1464,11 +1565,15 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
* @param searchRequest es查询请求参数 * @param searchRequest es查询请求参数
*/ */
private void printDSL(SearchRequest searchRequest) { private void printDSL(SearchRequest searchRequest) {
if (GlobalConfigCache.getGlobalConfig().isPrintDsl() && Objects.nonNull(searchRequest)) { Optional.ofNullable(searchRequest.source())
Optional.ofNullable(searchRequest.source()) .ifPresent(i -> doPrint(i.toString(), searchRequest.indices()));
.ifPresent(source -> LogUtils.info(BaseEsConstants.DSL_PREFIX }
+ "\nindex-name: " + org.springframework.util.StringUtils.arrayToCommaDelimitedString(searchRequest.indices())
+ "\nDSL" + source)); private void doPrint(String source, String[] indices) {
GlobalConfig globalConfig = GlobalConfigCache.getGlobalConfig();
if (globalConfig.isPrintDsl()) {
String prefix = globalConfig.isIKunMode() ? I_KUN_PREFIX : DSL_PREFIX;
LogUtils.info(prefix + "\nindex-name: " + String.join(",", indices) + "\nDSL" + source);
} }
} }
@ -1497,7 +1602,7 @@ public class BaseEsMapperImpl<T> implements BaseEsMapper<T> {
private String getRefreshPolicy() { private String getRefreshPolicy() {
// 防止傻狍子用户在全局中把刷新策略修改为GLOBAL // 防止傻狍子用户在全局中把刷新策略修改为GLOBAL
final RefreshPolicy refreshPolicy = EntityInfoHelper.getEntityInfo(entityClass).getRefreshPolicy(); final RefreshPolicy refreshPolicy = EntityInfoHelper.getEntityInfo(entityClass).getRefreshPolicy();
return refreshPolicy.equals(RefreshPolicy.GLOBAL) ? RefreshPolicy.NONE.getValue() : refreshPolicy.getValue(); return RefreshPolicy.GLOBAL.equals(refreshPolicy) ? RefreshPolicy.NONE.getValue() : refreshPolicy.getValue();
} }
/** /**

View File

@ -246,10 +246,14 @@ public class WrapperProcessor {
break; break;
case NESTED: case NESTED:
realField = getRealField(param.getColumn(), mappingColumnMap); realField = getRealField(param.getColumn(), mappingColumnMap);
String[] split = param.getColumn().split("\\."); String[] split = param.getColumn().split(SIGN);
queryBuilder = getBool(children, QueryBuilders.boolQuery(), entityInfo, split[split.length - 1]); String path = split[split.length - 1];
queryBuilder = QueryBuilders.nestedQuery(realField, queryBuilder, (ScoreMode) param.getVal()); queryBuilder = getBool(children, QueryBuilders.boolQuery(), entityInfo, path);
setBool(bool, queryBuilder, param.getPrevQueryType()); NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(realField, queryBuilder, (ScoreMode) param.getVal());
// 设置嵌套类型高亮查询参数
setNestedHighlight(path, param.getColumn(), nestedQueryBuilder, entityInfo);
// 设置bool查询参数
setBool(bool, nestedQueryBuilder, param.getPrevQueryType());
break; break;
default: default:
// just ignore,almost never happen // just ignore,almost never happen
@ -257,6 +261,27 @@ public class WrapperProcessor {
} }
} }
/**
* 设置嵌套类型高亮查询参数
*
* @param path 嵌套path
* @param column 字段
* @param nestedQueryBuilder 嵌套查询条件构造器
* @param entityInfo 实体信息缓存
*/
private static void setNestedHighlight(String path, String column, NestedQueryBuilder nestedQueryBuilder, EntityInfo entityInfo) {
// 嵌套类型的高亮查询语句构造
Class<?> pathClass = entityInfo.getPathClassMap().get(path);
Optional.ofNullable(pathClass)
.flatMap(i -> Optional.ofNullable(entityInfo.getNestedHighLightParamsMap().get(i)))
.ifPresent(i -> {
// 嵌套类型高亮字段名需要完整的path 例如users.faqs 所以此处用param.column而非path
HighlightBuilder highlightBuilder = initHighlightBuilder(i, column);
Optional.ofNullable(highlightBuilder)
.ifPresent(p -> nestedQueryBuilder.innerHit(new InnerHitBuilder().setHighlightBuilder(p)));
});
}
/** /**
* 设置节点的bool * 设置节点的bool
* *
@ -282,8 +307,10 @@ public class WrapperProcessor {
/** /**
* 递归获取子节点的bool * 递归获取子节点的bool
* *
* @param paramList 子节点参数列表 * @param paramList 子节点参数列表
* @param builder 新的根bool * @param builder 新的根bool
* @param entityInfo 实体信息缓存
* @param path 路径
* @return 子节点bool合集, 统一封装至入参builder中 * @return 子节点bool合集, 统一封装至入参builder中
*/ */
private static BoolQueryBuilder getBool(List<Param> paramList, BoolQueryBuilder builder, EntityInfo entityInfo, String path) { private static BoolQueryBuilder getBool(List<Param> paramList, BoolQueryBuilder builder, EntityInfo entityInfo, String path) {
@ -326,7 +353,7 @@ public class WrapperProcessor {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 设置高亮 // 设置高亮
setHighLight(entityInfo.getHighLightParams(), searchSourceBuilder); setHighLight(entityInfo.getHighlightParams(), searchSourceBuilder);
// 设置用户指定的各种排序规则 // 设置用户指定的各种排序规则
setSort(wrapper, mappingColumnMap, searchSourceBuilder); setSort(wrapper, mappingColumnMap, searchSourceBuilder);
@ -404,12 +431,23 @@ public class WrapperProcessor {
return; return;
} }
// 初始化高亮参数
HighlightBuilder highlightBuilder = initHighlightBuilder(highLightParams, null);
Optional.ofNullable(highlightBuilder).ifPresent(searchSourceBuilder::highlighter);
}
private static HighlightBuilder initHighlightBuilder(List<HighLightParam> highLightParams, String path) {
if (CollectionUtils.isEmpty(highLightParams)) {
return null;
}
// 封装高亮参数 // 封装高亮参数
HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder highlightBuilder = new HighlightBuilder();
highLightParams.forEach(highLightParam -> { highLightParams.forEach(highLightParam -> {
if (StringUtils.isNotBlank(highLightParam.getHighLightField())) { if (StringUtils.isNotBlank(highLightParam.getHighLightField())) {
//field // 嵌套类型 须追加其完整path前缀
HighlightBuilder.Field field = new HighlightBuilder.Field(highLightParam.getHighLightField()); String highlightField = Optional.ofNullable(path).map(i -> i + STR_SIGN + highLightParam.getHighLightField())
.orElse(highLightParam.getHighLightField());
HighlightBuilder.Field field = new HighlightBuilder.Field(highlightField);
field.highlighterType(highLightParam.getHighLightType().getValue()); field.highlighterType(highLightParam.getHighLightType().getValue());
highlightBuilder.field(field); highlightBuilder.field(field);
@ -419,7 +457,7 @@ public class WrapperProcessor {
Optional.ofNullable(highLightParam.getNumberOfFragments()).ifPresent(highlightBuilder::numOfFragments); Optional.ofNullable(highLightParam.getNumberOfFragments()).ifPresent(highlightBuilder::numOfFragments);
} }
}); });
searchSourceBuilder.highlighter(highlightBuilder); return highlightBuilder;
} }

View File

@ -257,7 +257,7 @@ public class EntityInfoHelper {
// 初始化封装HighLight注解信息 // 初始化封装HighLight注解信息
if (field.isAnnotationPresent(HighLight.class)) { if (field.isAnnotationPresent(HighLight.class)) {
initHighLightAnnotation(dbConfig, entityInfo, field); initHighLightAnnotation(dbConfig, entityInfo, field, entityInfo.getMappingColumnMap(), null);
// 此处无需返回true阻断流程,可防止用户未添加IndexField时,框架索引跳过读取此字段的信息 // 此处无需返回true阻断流程,可防止用户未添加IndexField时,框架索引跳过读取此字段的信息
} }
@ -373,38 +373,71 @@ public class EntityInfoHelper {
/** /**
* HighLight注解初始化 * HighLight注解初始化
* *
* @param dbConfig 索引配置 * @param dbConfig 索引配置
* @param entityInfo 实体信息 * @param entityInfo 实体信息
* @param field 字段 * @param field 字段
* @param mappingColumnMap 实体字段与es字段映射关系
* @param nestedClass 嵌套类
*/ */
private static void initHighLightAnnotation(GlobalConfig.DbConfig dbConfig, EntityInfo entityInfo, Field field) { private static void initHighLightAnnotation(GlobalConfig.DbConfig dbConfig, EntityInfo entityInfo, Field field,
Map<String, String> mappingColumnMap, Class<?> nestedClass) {
HighLight highLight = field.getAnnotation(HighLight.class); HighLight highLight = field.getAnnotation(HighLight.class);
String mappingField = highLight.mappingField(); String mappingField = highLight.mappingField();
if (StringUtils.isNotBlank(mappingField)) {
entityInfo.getNotSerializeField().add(mappingField); // 置入字段json序列化忽略缓存
} else { boolean skip = false;
if (StringUtils.isBlank(mappingField)) {
// 如果用户未指定高亮映射字段,则高亮映射字段用当前字段 // 如果用户未指定高亮映射字段,则高亮映射字段用当前字段
mappingField = field.getName(); mappingField = field.getName();
// 当使用当前字段作为高亮字段时,当前字段参与索引创建
skip = true;
}
if (!skip) {
// 添加无需序列化字段至缓存
if (nestedClass == null) {
entityInfo.getNotSerializeField().add(mappingField);
} else {
// 嵌套类型
Set<String> nestedNotSerializeFieldSet = Optional.ofNullable(entityInfo.getNestedNotSerializeField().get(nestedClass))
.orElse(new HashSet<>());
nestedNotSerializeFieldSet.add(mappingField);
entityInfo.getNestedNotSerializeField().put(nestedClass, nestedNotSerializeFieldSet);
}
} }
String customField = entityInfo.getMappingColumnMap().get(field.getName()); // 置入高亮字段与实体类中字段名对应关系缓存
String customField = mappingColumnMap.get(field.getName());
String realHighLightField = Objects.isNull(customField) ? field.getName() : customField; String realHighLightField = Objects.isNull(customField) ? field.getName() : customField;
if (dbConfig.isMapUnderscoreToCamelCase()) { if (dbConfig.isMapUnderscoreToCamelCase()) {
realHighLightField = StringUtils.camelToUnderline(realHighLightField); realHighLightField = StringUtils.camelToUnderline(realHighLightField);
} }
entityInfo.getHighlightFieldMap().putIfAbsent(realHighLightField, mappingField); if (nestedClass == null) {
entityInfo.getHighlightFieldMap().putIfAbsent(realHighLightField, mappingField);
} else {
Map<String, String> nestedHighlightFieldMap = Optional.ofNullable(entityInfo.getNestedHighlightFieldMap().get(nestedClass))
.orElse(new HashMap<>());
nestedHighlightFieldMap.putIfAbsent(realHighLightField, mappingField);
entityInfo.getNestedHighlightFieldMap().put(nestedClass, nestedHighlightFieldMap);
}
// 封装高亮参数 // 置入高亮查询参数缓存
HighLightParam highLightParam = new HighLightParam(); HighLightParam highlightParam = new HighLightParam();
highLightParam.setFragmentSize(highLight.fragmentSize()) highlightParam.setFragmentSize(highLight.fragmentSize())
.setPreTag(highLight.preTag()) .setPreTag(highLight.preTag())
.setPostTag(highLight.postTag()) .setPostTag(highLight.postTag())
.setHighLightField(realHighLightField) .setHighLightField(realHighLightField)
.setHighLightType(highLight.highLightType()); .setHighLightType(highLight.highLightType());
if (MINUS_ONE != highLight.numberOfFragments() && highLight.numberOfFragments() > ZERO) { if (MINUS_ONE != highLight.numberOfFragments() && highLight.numberOfFragments() > ZERO) {
highLightParam.setNumberOfFragments(highLight.numberOfFragments()); highlightParam.setNumberOfFragments(highLight.numberOfFragments());
}
if (nestedClass == null) {
entityInfo.getHighlightParams().add(highlightParam);
} else {
List<HighLightParam> nestedHighlightParams = Optional.ofNullable(entityInfo.getNestedHighLightParamsMap().get(nestedClass))
.orElse(new ArrayList<>());
nestedHighlightParams.add(highlightParam);
entityInfo.getNestedHighLightParamsMap().put(nestedClass, nestedHighlightParams);
} }
entityInfo.getHighLightParams().add(highLightParam);
} }
/** /**
@ -490,6 +523,10 @@ public class EntityInfoHelper {
mappingColumnMap.putIfAbsent(field.getName(), mappingColumn); mappingColumnMap.putIfAbsent(field.getName(), mappingColumn);
fieldTypeMap.putIfAbsent(field.getName(), fieldType.getType()); fieldTypeMap.putIfAbsent(field.getName(), fieldType.getType());
// 初始化封装嵌套类中的HighLight注解信息
if (field.isAnnotationPresent(HighLight.class)) {
initHighLightAnnotation(dbConfig, entityInfo, field, mappingColumnMap, nestedClass);
}
}); });
entityInfo.getNestedNotSerializeField().putIfAbsent(nestedClass, notSerializedFields); entityInfo.getNestedNotSerializeField().putIfAbsent(nestedClass, notSerializedFields);
entityInfo.getNestedClassColumnMappingMap().putIfAbsent(nestedClass, columnMappingMap); entityInfo.getNestedClassColumnMappingMap().putIfAbsent(nestedClass, columnMappingMap);

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<relativePath>../easy-es-parent</relativePath> <relativePath>../easy-es-parent</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es-parent</artifactId> <artifactId>easy-es-parent</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<name>easy-es-parent</name> <name>easy-es-parent</name>
<description>easy use for elastic search</description> <description>easy use for elastic search</description>

View File

@ -9,7 +9,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es</artifactId> <artifactId>easy-es</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
</parent> </parent>
<properties> <properties>

View File

@ -1,5 +1,7 @@
package org.dromara.easyes.sample.entity; package org.dromara.easyes.sample.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import org.dromara.easyes.annotation.HighLight; import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField; import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId; import org.dromara.easyes.annotation.IndexId;
@ -8,8 +10,6 @@ import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldStrategy; import org.dromara.easyes.annotation.rely.FieldStrategy;
import org.dromara.easyes.annotation.rely.FieldType; import org.dromara.easyes.annotation.rely.FieldType;
import org.dromara.easyes.annotation.rely.IdType; import org.dromara.easyes.annotation.rely.IdType;
import lombok.Data;
import lombok.experimental.Accessors;
/** /**
* es 数据模型 * es 数据模型
@ -18,7 +18,7 @@ import lombok.experimental.Accessors;
**/ **/
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true,maxResultWindow = 100) @IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, maxResultWindow = 100)
public class Document { public class Document {
/** /**
* es中的唯一id,如果你想自定义es中的id为你提供的id,比如MySQL中的id,请将注解中的type指定为customize或直接在全局配置文件中指定,如此id便支持任意数据类型) * es中的唯一id,如果你想自定义es中的id为你提供的id,比如MySQL中的id,请将注解中的type指定为customize或直接在全局配置文件中指定,如此id便支持任意数据类型)
@ -63,7 +63,7 @@ public class Document {
/** /**
* 自定义字段名称 * 自定义字段名称
*/ */
@IndexField(value = "wu-la", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_SMART,fieldData = true) @IndexField(value = "wu-la", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_SMART, fieldData = true)
private String customField; private String customField;
/** /**

View File

@ -6,12 +6,13 @@ easy-es:
password: WG7WVmuNMtM4GwNYkyWH password: WG7WVmuNMtM4GwNYkyWH
keep-alive-millis: 18000 keep-alive-millis: 18000
global-config: global-config:
i-kun-mode: true
process-index-mode: smoothly process-index-mode: smoothly
async-process-index-blocking: true async-process-index-blocking: true
print-dsl: false print-dsl: false
db-config: db-config:
map-underscore-to-camel-case: true map-underscore-to-camel-case: true
table-prefix: dev_ index-prefix: dev_
id-type: customize id-type: customize
field-strategy: not_empty field-strategy: not_empty
refresh-policy: immediate refresh-policy: immediate

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es</artifactId> <artifactId>easy-es</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
</parent> </parent>
<artifactId>easy-es-test</artifactId> <artifactId>easy-es-test</artifactId>

View File

@ -4,10 +4,11 @@ package org.dromara.easyes.test.entity;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField; import org.dromara.easyes.annotation.IndexField;
/** /**
* 文件描述 * 问答
* *
* @ProductName: Hundsun HEP * @ProductName: Hundsun HEP
* @ProjectName: easy-es * @ProjectName: easy-es
@ -26,7 +27,14 @@ import org.dromara.easyes.annotation.IndexField;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class Faq { public class Faq {
/**
* 问题 高亮内容直接覆盖在原字段值上进行返回,故不需要指定高亮注解中的mappingField
*/
@HighLight
private String faqName; private String faqName;
@IndexField(value = "answer") @IndexField(value = "answer")
/**
* 答案
*/
private String faqAnswer; private String faqAnswer;
} }

View File

@ -1,9 +1,9 @@
package org.dromara.easyes.test.entity; package org.dromara.easyes.test.entity;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.dromara.easyes.annotation.HighLight;
import org.dromara.easyes.annotation.IndexField; import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.rely.Analyzer; import org.dromara.easyes.annotation.rely.Analyzer;
import org.dromara.easyes.annotation.rely.FieldType; import org.dromara.easyes.annotation.rely.FieldType;
@ -17,13 +17,21 @@ import java.util.Set;
**/ **/
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor
public class User { public class User {
/**
* 用户名
*/
@IndexField(value = "user_name", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART) @IndexField(value = "user_name", fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART)
@HighLight(mappingField = "highlightUsername")
private String username; private String username;
/**
* 年龄
*/
@IndexField(fieldType = FieldType.INTEGER) @IndexField(fieldType = FieldType.INTEGER)
private Integer age; private Integer age;
/**
* 密码
*/
@IndexField(fieldType = FieldType.KEYWORD) @IndexField(fieldType = FieldType.KEYWORD)
private String password; private String password;
/** /**
@ -31,4 +39,15 @@ public class User {
*/ */
@IndexField(fieldType = FieldType.NESTED, nestedClass = Faq.class) @IndexField(fieldType = FieldType.NESTED, nestedClass = Faq.class)
private Set<Faq> faqs; private Set<Faq> faqs;
/**
* 高亮显示的内容
*/
private String highlightUsername;
public User(String username, Integer age, String password, Set<Faq> faqs) {
this.username = username;
this.age = age;
this.password = password;
this.faqs = faqs;
}
} }

View File

@ -11,6 +11,7 @@ import org.dromara.easyes.test.mapper.DocumentMapper;
import org.elasticsearch.geometry.Point; import org.elasticsearch.geometry.Point;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -34,6 +35,15 @@ public class NestedTest {
private DocumentMapper documentMapper; private DocumentMapper documentMapper;
@Test @Test
@Order(0)
public void testCreateIndex() {
// 初始化创建索引,配置开启手动挡后执行
final Boolean success = documentMapper.createIndex();
Assertions.assertTrue(success);
}
@Test
@Order(1)
public void testInsert() { public void testInsert() {
// 测试插入数据 // 测试插入数据
Document document = new Document(); Document document = new Document();
@ -49,14 +59,14 @@ public class NestedTest {
document.setStarNum(1); document.setStarNum(1);
List<User> users = new ArrayList<>(); List<User> users = new ArrayList<>();
Set<Faq> faqs = new HashSet<>(); Set<Faq> faqs = new HashSet<>();
faqs.add(new Faq("问题1", "回答1")); faqs.add(new Faq("q1", "回答1"));
faqs.add(new Faq("问题2", "回答2")); faqs.add(new Faq("q2", "回答2"));
Set<Faq> faqs1 = new HashSet<>(); Set<Faq> faqs1 = new HashSet<>();
faqs1.add(new Faq("问题3", "回答3")); faqs1.add(new Faq("q4", "回答3"));
faqs1.add(new Faq("问题4", "回答4")); faqs1.add(new Faq("q3", "回答4"));
users.add(new User("用户1", 18, "12345", faqs)); users.add(new User("u1", 18, "12345", faqs));
users.add(new User("用户2", 19, "123", faqs1)); users.add(new User("u2", 19, "123", faqs1));
document.setUsers(users); document.setUsers(users);
int successCount = documentMapper.insert(document); int successCount = documentMapper.insert(document);
Assertions.assertEquals(successCount, 1); Assertions.assertEquals(successCount, 1);
@ -65,19 +75,20 @@ public class NestedTest {
users.clear(); users.clear();
faqs.clear(); faqs.clear();
faqs1.clear(); faqs1.clear();
faqs.add(new Faq("question1", "answer1")); faqs.add(new Faq("q1", "answer1"));
faqs.add(new Faq("question2", "answer2")); faqs.add(new Faq("q2", "answer2"));
faqs1.add(new Faq("q3", "a3")); faqs1.add(new Faq("q3", "a3"));
faqs1.add(new Faq("q4", "a4")); faqs1.add(new Faq("q4", "a4"));
users.add(new User("user1", 8, "12345", faqs)); users.add(new User("u3", 8, "12345", faqs));
users.add(new User("u2", 9, "54321", faqs1)); users.add(new User("u4", 9, "54321", faqs1));
document.setUsers(users); document.setUsers(users);
successCount = documentMapper.insert(document); successCount = documentMapper.insert(document);
Assertions.assertEquals(successCount, 1); Assertions.assertEquals(successCount, 1);
} }
@Test @Test
@Order(2)
public void testNestedMatch() { public void testNestedMatch() {
// 嵌套查询 查询年龄等于18或8且密码等于12345的数据 // 嵌套查询 查询年龄等于18或8且密码等于12345的数据
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>(); LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
@ -89,10 +100,10 @@ public class NestedTest {
// 嵌套类型中的字段获取可以用FieldUtils.val或直接传入字符串 // 嵌套类型中的字段获取可以用FieldUtils.val或直接传入字符串
LambdaEsQueryWrapper<Document> wrapper1 = new LambdaEsQueryWrapper<>(); LambdaEsQueryWrapper<Document> wrapper1 = new LambdaEsQueryWrapper<>();
wrapper1.eq(Document::getTitle,"老汉") wrapper1.eq(Document::getTitle, "老汉")
.nested("users.faqs", w -> w.eq("users.faqs.answer", "a4") .nested("users.faqs", w -> w.eq("users.faqs.answer", "a4")
.match("users.faqs.faq_name", "q4")) .match("users.faqs.faq_name", "q4"))
.nested("users", w -> w.between("users.age", 1, 30)) .nested("users", w -> w.match("users.user_name", "u3"))
.match(Document::getCreator, "吃饭"); .match(Document::getCreator, "吃饭");
List<Document> documents1 = documentMapper.selectList(wrapper1); List<Document> documents1 = documentMapper.selectList(wrapper1);
System.out.println(documents1); System.out.println(documents1);
@ -106,7 +117,7 @@ public class NestedTest {
System.out.println(documents2); System.out.println(documents2);
LambdaEsQueryWrapper<Document> wrapper3 = new LambdaEsQueryWrapper<>(); LambdaEsQueryWrapper<Document> wrapper3 = new LambdaEsQueryWrapper<>();
wrapper3.nested("users.faqs",w->w.match("users.faqs.faq_name", "q3").or().match("users.faqs.faq_name","q4")); wrapper3.nested("users.faqs", w -> w.match("users.faqs.faq_name", "q3").or().match("users.faqs.faq_name", "q4"));
List<Document> documents3 = documentMapper.selectList(wrapper3); List<Document> documents3 = documentMapper.selectList(wrapper3);
System.out.println(documents3); System.out.println(documents3);
} }

View File

@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
/** /**
* searchAfter测试 * searchAfter测试
@ -32,9 +33,38 @@ public class SearchAfterTest {
//重现bug需要注释掉searchAfter中对from的校验 //重现bug需要注释掉searchAfter中对from的校验
// lambdaEsQueryWrapper.from(10); // lambdaEsQueryWrapper.from(10);
SAPageInfo<Document> saPageInfo = documentMapper.searchAfterPage(lambdaEsQueryWrapper, null, 10); SAPageInfo<Document> saPageInfo = documentMapper.searchAfterPage(lambdaEsQueryWrapper, null, 10);
//第一页 //第一页
System.out.println(saPageInfo); System.out.println(saPageInfo);
Assertions.assertEquals(10, saPageInfo.getList().size()); Assertions.assertEquals(10, saPageInfo.getList().size());
} }
@Test
public void test1() {
documentMapper.createIndex();
for (int i = 0; i < 30; i++) {
Document document = new Document();
document.setEsId(String.valueOf(i));
document.setTitle("测试标题" + i);
document.setContent("测试内容" + i);
documentMapper.insert(document);
}
}
@Test
public void test2() {
LambdaEsQueryWrapper<Document> wrapper = EsWrappers.lambdaQuery(Document.class);
wrapper.match(Document::getContent, "测试");
wrapper.orderByDesc(Document::getEsId);
// 第一页,可传null,查完把saPageInfo返回给前端
SAPageInfo<Document> saPageInfo = documentMapper.searchAfterPage(wrapper, null, 10);
System.out.println(saPageInfo);
// 第二页,从saPageInfo中把上一次的nextSearchAfter回传给后端
List<Object> nextSearchAfter = saPageInfo.getNextSearchAfter();
SAPageInfo<Document> saPageInfo1 = documentMapper.searchAfterPage(wrapper, nextSearchAfter, 10);
System.out.println(saPageInfo1);
}
} }

View File

@ -6,6 +6,7 @@ easy-es:
# password: WG7WVmuNMtM4GwNYkyWH # password: WG7WVmuNMtM4GwNYkyWH
keep-alive-millis: 18000 keep-alive-millis: 18000
global-config: global-config:
i-kun-mode: true
process-index-mode: manual process-index-mode: manual
async-process-index-blocking: true async-process-index-blocking: true
print-dsl: true print-dsl: true

View File

@ -6,7 +6,7 @@
<groupId>org.dromara.easy-es</groupId> <groupId>org.dromara.easy-es</groupId>
<artifactId>easy-es</artifactId> <artifactId>easy-es</artifactId>
<version>2.0.0-beta4</version> <version>2.0.0-beta5</version>
<name>easy-es</name> <name>easy-es</name>
<description>easy use for elastic search</description> <description>easy use for elastic search</description>