- fix: 索引变动对比判定规则完善
This commit is contained in:
xpc 2025-05-06 20:21:24 +08:00
parent 3bc2a7a860
commit 8b2719e42f
7 changed files with 211 additions and 18 deletions

View File

@ -194,10 +194,6 @@ public interface BaseEsConstants {
* 更新索引时自动创建的索引后缀s1
*/
String S1_SUFFIX = "_s1";
/**
* 分布式锁提示内容
*/
String DISTRIBUTED_LOCK_TIP_JSON = "{\"tip\":\"Do not delete unless deadlock occurs\"}";
/**
* 获取/释放 分布式锁 最大失败重试次数
*/

View File

@ -32,5 +32,5 @@ public class EsIndexInfo {
/**
* 索引字段信息
*/
private TypeMapping.Builder mapping;
private TypeMapping.Builder builder;
}

View File

@ -40,7 +40,7 @@ public abstract class Generator {
public void generateEntity(GeneratorConfig config, ElasticsearchClient client) {
// get index info
EsIndexInfo esIndexInfo = IndexUtils.getIndexInfo(client, config.getIndexName());
TypeMapping.Builder mapping = esIndexInfo.getMapping();
TypeMapping.Builder mapping = esIndexInfo.getBuilder();
if (mapping == null) {
return;
}

View File

@ -323,9 +323,8 @@ public class IndexUtils {
.size(mappings.size())
.source(mappings.source())
.runtime(mappings.runtime())
.enabled(mappings.enabled())
;
esIndexInfo.setMapping(builder);
.enabled(mappings.enabled());
esIndexInfo.setBuilder(builder);
}
return esIndexInfo;
@ -1088,10 +1087,13 @@ public class IndexUtils {
// 根据实体类注解信息构建mapping
entityInfo.setIndexEqualStage(true);
TypeMapping.Builder mapping = IndexUtils.initMapping(entityInfo, esIndexParamList);
TypeMapping.Builder builderFromEntity = IndexUtils.initMapping(entityInfo, esIndexParamList);
// 与查询到的已知index对比是否发生改变
return !mapping.equals(esIndexInfo.getMapping());
TypeMapping.Builder builderFromIndex = esIndexInfo.getBuilder();
Map<String, Property> propertiesOfEntity = builderFromEntity.build().properties();
Map<String, Property> propertiesOfIndex = builderFromIndex.build().properties();
return !PropertyComparator.isPropertyMapEqual(propertiesOfEntity,propertiesOfIndex);
}
/**
@ -1174,7 +1176,8 @@ public class IndexUtils {
);
SearchResponse<Map<String, String>> response = null;
try {
response = client.search(searchRequest, new TypeReference<Map<String, Object>>(){}.getType());
response = client.search(searchRequest, new TypeReference<Map<String, Object>>() {
}.getType());
} catch (Throwable e) {
LogUtils.warn("Active failed, The machine that acquired lock is migrating, will try again later");
}

View File

@ -7,6 +7,8 @@ import co.elastic.clients.elasticsearch.core.*;
import org.dromara.easyes.common.constants.BaseEsConstants;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.dromara.easyes.common.constants.BaseEsConstants.LOCK_INDEX;
@ -24,6 +26,14 @@ public class LockUtils {
* 重试等待时间
*/
private final static Integer WAIT_SECONDS = 1;
/**
* 分布式锁内容
*/
private final static Map<String,Object> LOCK_DOC;
static {
LOCK_DOC = new HashMap<>(2);
LOCK_DOC.put("tip","Do not delete unless deadlock occurs");
}
/**
* 尝试获取es分布式锁
@ -64,12 +74,12 @@ public class LockUtils {
*/
private static boolean createLock(ElasticsearchClient client, String idValue) {
IndexRequest<?> indexRequest = IndexRequest.of(x -> x
.index(LOCK_INDEX).id(idValue).document(BaseEsConstants.DISTRIBUTED_LOCK_TIP_JSON)
.index(LOCK_INDEX).id(idValue).document(LOCK_DOC)
);
IndexResponse response;
try {
response = client.index(indexRequest);
} catch (IOException e) {
} catch (Exception e) {
e.printStackTrace();
return Boolean.FALSE;
}

View File

@ -0,0 +1,184 @@
package org.dromara.easyes.core.toolkit;
import co.elastic.clients.elasticsearch._types.mapping.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 索引属性变化比较器
* <p>
* Copyright © 2022 xpc1024 All Rights Reserved
**/
public class PropertyComparator {
public static boolean isPropertyMapEqual(Map<String, Property> map1, Map<String, Property> map2) {
// 直接引用相等性检查
if (map1 == map2) {
return true;
}
// 基础检查大小是否一致
if (map1.size() != map2.size()) {
return false;
}
// 遍历所有键进行深度比较
for (String key : map1.keySet()) {
Property prop1 = map1.get(key);
// 检查键是否存在
if (!map2.containsKey(key)) {
return false;
}
Property prop2 = map2.get(key);
// 深度比较属性
if (!deepCompareProperties(prop1, prop2)) {
return false;
}
}
return true;
}
private static boolean deepCompareProperties(Property prop1, Property prop2) {
// 快速引用相等检查
if (prop1 == prop2) return true;
// 类型基础检查
if (prop1._kind() != prop2._kind()) return false;
// 按类型分发处理逻辑
switch (prop1._kind()) {
case Nested:
return compareNested(prop1.nested(), prop2.nested());
case Object:
return compareObject(prop1.object(), prop2.object());
case Text:
return compareText(prop1.text(), prop2.text());
case Keyword:
return compareKeyword(prop1.keyword(), prop2.keyword());
case Date:
return compareDate(prop1.date(), prop2.date());
case GeoPoint:
return compareGeoPoint(prop1.geoPoint(), prop2.geoPoint());
case Ip:
return compareIp(prop1.ip(), prop2.ip());
case ScaledFloat:
return compareScaledFloat(prop1.scaledFloat(), prop2.scaledFloat());
case Completion:
return compareCompletion(prop1.completion(), prop2.completion());
case Flattened:
return compareFlattened(prop1.flattened(), prop2.flattened());
case DenseVector:
return compareDenseVector(prop1.denseVector(), prop2.denseVector());
case GeoShape:
return compareGeoShape(prop1.geoShape(), prop2.geoShape());
case Wildcard:
return compareWildcard(prop1.wildcard(), prop2.wildcard());
case Byte:
case Short:
case Float:
case HalfFloat:
case Double:
case Integer:
case Long:
return compareNumberType((NumberPropertyBase) prop1._get(), (NumberPropertyBase) prop2._get());
default:
// 其他非常用类型 比较了key和type相同即认为相同 后续会随对应功能迭代继续完善
return true;
}
}
// 新增GeoShape和Wildcard的比较方法
private static boolean compareGeoShape(GeoShapeProperty p1, GeoShapeProperty p2) {
return Objects.equals(p1.ignoreMalformed(), p2.ignoreMalformed()) &&
Objects.equals(p1.ignoreZValue(), p2.ignoreZValue()) &&
Objects.equals(p1.coerce(), p2.coerce()) &&
Objects.equals(p1.orientation(), p2.orientation());
}
private static boolean compareNumberType(NumberPropertyBase p1, NumberPropertyBase p2) {
return Objects.equals(p1.docValues(), p2.docValues()) &&
Objects.equals(p1.ignoreMalformed(), p2.ignoreMalformed());
}
private static boolean compareWildcard(WildcardProperty p1, WildcardProperty p2) {
return Objects.equals(p1.ignoreAbove(), p2.ignoreAbove()) &&
unorderedEquals(p1.copyTo(), p2.copyTo());
}
// 各类型详细比较逻辑
private static boolean compareNested(NestedProperty p1, NestedProperty p2) {
return Objects.equals(p1.dynamic(), p2.dynamic()) &&
isPropertyMapEqual(p1.properties(), p2.properties());
}
private static boolean compareObject(ObjectProperty p1, ObjectProperty p2) {
return Objects.equals(p1.dynamic(), p2.dynamic()) &&
isPropertyMapEqual(p1.properties(), p2.properties());
}
private static boolean compareText(TextProperty p1, TextProperty p2) {
return Objects.equals(p1.analyzer(), p2.analyzer()) &&
Objects.equals(p1.searchAnalyzer(), p2.searchAnalyzer()) &&
unorderedEquals(p1.copyTo(), p2.copyTo()) &&
isPropertyMapEqual(p1.fields(), p2.fields());
}
private static boolean compareKeyword(KeywordProperty p1, KeywordProperty p2) {
return Objects.equals(p1.ignoreAbove(), p2.ignoreAbove()) &&
unorderedEquals(p1.copyTo(), p2.copyTo());
}
private static boolean compareDate(DateProperty p1, DateProperty p2) {
return Objects.equals(p1.format(), p2.format()) &&
Objects.equals(p1.ignoreMalformed(), p2.ignoreMalformed());
}
private static boolean compareGeoPoint(GeoPointProperty p1, GeoPointProperty p2) {
return Objects.equals(p1.ignoreMalformed(), p2.ignoreMalformed()) &&
Objects.equals(p1.ignoreZValue(), p2.ignoreZValue());
}
private static boolean compareIp(IpProperty p1, IpProperty p2) {
return Objects.equals(p1.boost(), p2.boost()) &&
Objects.equals(p1.docValues(), p2.docValues());
}
private static boolean compareScaledFloat(ScaledFloatNumberProperty p1,
ScaledFloatNumberProperty p2) {
return Objects.equals(p1.scalingFactor(), p2.scalingFactor()) &&
Objects.equals(p1.coerce(), p2.coerce());
}
private static boolean compareCompletion(CompletionProperty p1,
CompletionProperty p2) {
return Objects.equals(p1.preserveSeparators(), p2.preserveSeparators()) &&
Objects.equals(p1.preservePositionIncrements(),
p2.preservePositionIncrements());
}
private static boolean compareFlattened(FlattenedProperty p1,
FlattenedProperty p2) {
return Objects.equals(p1.boost(), p2.boost()) &&
Objects.equals(p1.depthLimit(), p2.depthLimit());
}
private static boolean compareDenseVector(DenseVectorProperty p1,
DenseVectorProperty p2) {
return Objects.equals(p1.dims(), p2.dims()) &&
Objects.equals(p1.similarity(), p2.similarity());
}
// 辅助方法处理无序集合比较
private static <T> boolean unorderedEquals(List<T> list1, List<T> list2) {
if (list1 == list2) return true;
if (list1 == null || list2 == null) return false;
return new HashSet<>(list1).equals(new HashSet<>(list2));
}
}