diff --git a/easy-es-common/src/main/java/org/dromara/easyes/common/enums/EsQueryTypeEnum.java b/easy-es-common/src/main/java/org/dromara/easyes/common/enums/EsQueryTypeEnum.java index 2d6362a8..b2a4b887 100644 --- a/easy-es-common/src/main/java/org/dromara/easyes/common/enums/EsQueryTypeEnum.java +++ b/easy-es-common/src/main/java/org/dromara/easyes/common/enums/EsQueryTypeEnum.java @@ -70,11 +70,6 @@ public enum EsQueryTypeEnum { GEO_POLYGON, GEO_SHAPE_ID, GEO_SHAPE, - /** - * 向量查询 - */ - ANN, - KNN, /** * 父子类型查询 */ diff --git a/easy-es-common/src/main/java/org/dromara/easyes/common/property/GlobalConfig.java b/easy-es-common/src/main/java/org/dromara/easyes/common/property/GlobalConfig.java index 37da1f64..e4fd629c 100644 --- a/easy-es-common/src/main/java/org/dromara/easyes/common/property/GlobalConfig.java +++ b/easy-es-common/src/main/java/org/dromara/easyes/common/property/GlobalConfig.java @@ -100,14 +100,7 @@ public class GlobalConfig { * Whether to intelligently add the. keyword suffix to the field. This configuration is enabled by default. The field type is KEYWORD only for annotation configuration_ The String field of TEXT or unconfigured type takes effect and only takes effect when the query requires that the field be of keyword type, so it is called smart! 是否智能为字段添加.keyword后缀 默认开启 此配置仅对注解配置字段类型为KEYWORD_TEXT或未配置类型的String字段生效,并且只会在查询要求该字段必须为keyword类型的查询中才生效,因此谓之智能! */ private boolean smartAddKeywordSuffix = true; - /** - * whether to enable knn-plugin. This configuration is enabled by default.If the plugin is not installed, it can be turned off temporarily (not recommended, poor performance). 是否开启knn插件 - 默认开启,若未安装该插件则可临时配置关闭(不推荐,性能表现差) - */ - private boolean enableKnnPlugin = true; - /** - * default date format 默认日期format格式 - */ private String defaultDateFormat = DEFAULT_DATE_TIME_FORMAT; } } diff --git a/easy-es-core/src/main/java/org/dromara/easyes/core/biz/EntityInfo.java b/easy-es-core/src/main/java/org/dromara/easyes/core/biz/EntityInfo.java index abb29c3b..c180ed11 100644 --- a/easy-es-core/src/main/java/org/dromara/easyes/core/biz/EntityInfo.java +++ b/easy-es-core/src/main/java/org/dromara/easyes/core/biz/EntityInfo.java @@ -224,10 +224,6 @@ public class EntityInfo { * 是否判定索引相同阶段 */ private boolean indexEqualStage; - /** - * 是否开启knn插件 - 默认开启,若未安装该插件则可临时配置关闭(不推荐,性能表现差) - */ - private boolean enableKnnPlugin; /** * 获取需要进行查询的字段列表 diff --git a/easy-es-core/src/main/java/org/dromara/easyes/core/conditions/function/Func.java b/easy-es-core/src/main/java/org/dromara/easyes/core/conditions/function/Func.java index acfe1184..10c6dd5f 100644 --- a/easy-es-core/src/main/java/org/dromara/easyes/core/conditions/function/Func.java +++ b/easy-es-core/src/main/java/org/dromara/easyes/core/conditions/function/Func.java @@ -1742,49 +1742,4 @@ public interface Func extends Serializable { * @return wrapper */ Children bucketOrder(boolean condition, List> bucketOrders); - - default Children knn(R column, float[] queryVec, int k) { - return knn(true, column, queryVec, k); - } - - default Children knn(boolean condition, R column, float[] queryVec, int k) { - return knn(condition, FieldUtils.getFieldName(column), queryVec, k); - } - - /** - * knn算法向量查询 - * - * @param condition 执行条件 - * @param column 字段 - * @param queryVec 查询向量 - * @param k 需要返回的最相似的结果数量 - * @return wrapper - */ - Children knn(boolean condition, String column, float[] queryVec, int k); - - default Children ann(R column, float[] queryVec, int k) { - return ann(true, column, queryVec, k, k * 10); - } - - default Children ann(R column, float[] queryVec, int k, int numCandidates) { - return ann(true, column, queryVec, k, numCandidates); - } - - - default Children ann(boolean condition, R column, float[] queryVec, int k, int numCandidates) { - return ann(condition, FieldUtils.getFieldName(column), queryVec, k, numCandidates); - } - - - /** - * ann算法向量查询 - * - * @param condition 执行条件 - * @param column 字段 - * @param queryVec 查询向量 - * @param k 需要返回的最相似的结果数量 - * @param numCandidates 候选数量 - * @return wrapper - */ - Children ann(boolean condition, String column, float[] queryVec, int k, int numCandidates); } diff --git a/easy-es-core/src/main/java/org/dromara/easyes/core/kernel/AbstractChainWrapper.java b/easy-es-core/src/main/java/org/dromara/easyes/core/kernel/AbstractChainWrapper.java index e901469a..1b9d4991 100644 --- a/easy-es-core/src/main/java/org/dromara/easyes/core/kernel/AbstractChainWrapper.java +++ b/easy-es-core/src/main/java/org/dromara/easyes/core/kernel/AbstractChainWrapper.java @@ -776,16 +776,4 @@ public abstract class AbstractChainWrapper q.parentId(p -> p.type(realField).id((String) param.getVal()))); @@ -309,7 +288,6 @@ public class WrapperProcessor { // 设置bool查询参数 setBool(bool, Query.of(x -> x.nested(nestedQueryBuilder.build())), param.getPrevQueryType()); break; - case HAS_PARENT: // 如果用户没指定type框架可根据entityInfo上下文自行推断出其父type String column = Optional.ofNullable(param.getColumn()).orElse(entityInfo.getParentJoinAlias()); @@ -492,10 +470,9 @@ public class WrapperProcessor { /** * 获取兜底索引名称 - * * @param entityClass 实体类 - * @param indexName 索引名 - * @param 泛型 + * @param indexName 索引名 + * @param 泛型 * @return 索引名称 */ public static String getIndexName(Class entityClass, String indexName) { @@ -510,8 +487,8 @@ public class WrapperProcessor { * 获取兜底索引名称数组 * * @param entityClass 实体类 - * @param indexNames 原始索引名称数组 - * @param 泛型 + * @param indexNames 原始索引名称数组 + * @param 泛型 * @return 目标索引名称数组 */ public static List getIndexName(Class entityClass, String[] indexNames) { @@ -529,10 +506,9 @@ public class WrapperProcessor { /** * 获取兜底索引名称数组 - * * @param entityClass 实体类 - * @param indexNames 原始索引名称数组 - * @param 泛型 + * @param indexNames 原始索引名称数组 + * @param 泛型 * @return 目标索引名称数组 */ public static List getIndexName(Class entityClass, Collection indexNames) { @@ -808,127 +784,4 @@ public class WrapperProcessor { throw new IllegalArgumentException(); } } - - - /** - * 方法1: 构建一个 KNN (近似最近邻) 查询。 - *

- * 由于此方法签名中没有 'k',我们将调用 buildKnnQuery 并使用一个预设的默认值。 - * - * @param column 进行向量搜索的 dense_vector 字段名。 - * @param queryVec 查询向量。 - * @return 用于Elasticsearch搜索请求的Query对象。 - */ - private static Query buildKnnQuery(String column, float[] queryVec, int k) { - return buildAnnQuery(column, queryVec, k, k * 10); - } - - /** - * 方法2: 构建一个 ANN (K最近邻) 查询。 - *

- * 此实现通过构造一个JSON字符串并使用 Query.withJson() 方法来创建查询, - * 以兼容不包含原生 KnnQuery Builder 的 7.17.28 客户端版本。 - * - * @param column 进行向量搜索的 dense_vector 字段名。 - * @param queryVec 查询向量。 - * @param k 需要返回的最相似的结果数量。 - * @param numCandidates 候选数量 - * @return 用于Elasticsearch搜索请求的Query对象。 - */ - private static Query buildAnnQuery(String column, float[] queryVec, int k, int numCandidates) { - if (queryVec == null || queryVec.length == 0) { - throw new IllegalArgumentException("查询向量(queryVec)不能为空。"); - } - if (k <= 0) { - throw new IllegalArgumentException("K值必须为正整数。"); - } - - // 1. 将 float[] 转换为 JSON 数组格式的字符串, e.g., "[0.1, 0.5, -0.2]" - // 1. 使用StringJoiner安全构建JSON数组字符串(兼容JDK 8) - StringJoiner sj = new StringJoiner(", ", "[", "]"); - for (float v : queryVec) { - sj.add(String.valueOf(v)); // 直接转字符串,行为等同于Float::toString - } - String vectorAsString = sj.toString(); - - // 2. 构建完整的 KNN 查询 JSON 字符串 - String knnQueryJson = String.format( - "{" + - " \"knn\": {" + - " \"field\": \"%s\"," + - " \"query_vector\": %s," + - " \"k\": %d," + - " \"num_candidates\": %d" + - " }" + - "}", - column, - vectorAsString, - k, - numCandidates - ); - - // 3. 使用 withJson 方法将 JSON 字符串包装成 Query 对象 - // Query.of() 接受一个 lambda,我们用它来配置查询变体 - // q.withJson() 接受一个 Reader,所以我们用 StringReader 包装我们的 JSON 字符串 - return Query.of(q -> q.withJson(new StringReader(knnQueryJson))); - } - - - /** - * 方法1: 构建一个基于 script_score 的 kNN 查询。 - * 这种方法使用 Elasticsearch 的内建脚本能力进行向量相似度计算(例如余弦相似度), - * 它是一种精确的 K-NN 搜索,但在大数据集上性能可能不如专门的 k-NN 插件。 - * - * @param column 包含向量的字段名 (类型应为 dense_vector) - * @param queryVec 用于查询的浮点数组向量。 - * @return 用于 script_score 的 Query 对象。 - */ - private static Query buildKnnQueryWithPlugin(String column, float[] queryVec, int k) { - // Painless 脚本,用于计算余弦相似度。 - // Elasticsearch 的 cosineSimilarity 返回值在 [-1, 1] 之间。 - // ES 的 score 要求为非负数,所以 +1.0 将其范围移动到 [0, 2]。 - // 分数越高,表示相似度越高。 - String scriptSource = "cosineSimilarity(params.query_vector, doc['" + column + "']) + 1.0"; - Map params = new HashMap<>(); - params.put("query_vector", JsonData.of(queryVec)); - params.put("k", JsonData.of(k)); - - ScriptScoreQuery scriptScoreQuery = ScriptScoreQuery.of(ssq -> ssq - // 基础查询,通常使用 match_all 搜索所有文档 - .query(q -> q.matchAll(ma -> ma)) - // 定义脚本和参数 - .script(s -> s - .inline(i -> i - .source(scriptSource) - .params(params) - ) - ) - ); - - return new Query(scriptScoreQuery); - } - - /** - * 方法2: 构建一个使用 K-NN 插件的查询。 - * 这种方法依赖于 OpenDistro/OpenSearch 的 k-NN 插件,它提供了专门的 `knn` 查询类型, - * 用于执行高效的近似最近邻(ANN)搜索。 - * 注意:因为 'knn' 不是 Elasticsearch 官方原生支持的查询类型(在7.x版本中), - * 我们需要使用 `_custom` 方法来构建这个自定义查询。 - * - * @param column 包含向量的字段名 (类型应为 knn_vector)。 - * @param queryVec 用于查询的浮点数组向量。 - * @param k 期望返回的最近邻结果数量。 - * @param numCandidates 候选数量 - * @return 用于 k-NN 插件的 Query 对象。 - */ - private static Query buildAnnQueryWithPlugin(String column, float[] queryVec, int k, int numCandidates) { - // 构建完整的自定义查询 payload - Map knnQueryPayload = new LinkedHashMap<>(); - knnQueryPayload.put("field", column); - knnQueryPayload.put("query_vector", queryVec); - knnQueryPayload.put("k", k); - knnQueryPayload.put("num_candidates", numCandidates); - // 使用 _custom 方法构建非标准的 "knn" 查询 - return Query.of(q -> q._custom("knn", knnQueryPayload)); - } } diff --git a/easy-es-core/src/main/java/org/dromara/easyes/core/toolkit/EntityInfoHelper.java b/easy-es-core/src/main/java/org/dromara/easyes/core/toolkit/EntityInfoHelper.java index cfd21b4d..75eb7b9c 100644 --- a/easy-es-core/src/main/java/org/dromara/easyes/core/toolkit/EntityInfoHelper.java +++ b/easy-es-core/src/main/java/org/dromara/easyes/core/toolkit/EntityInfoHelper.java @@ -29,7 +29,10 @@ import static org.dromara.easyes.common.constants.BaseEsConstants.*; * Copyright © 2021 xpc1024 All Rights Reserved **/ public class EntityInfoHelper { - + /** + * 获取索引settings方法名 + */ + private final static String GET_SETTINGS_METHOD = "getSettings"; /** * 储存反射类表信息 */ @@ -87,8 +90,6 @@ public class EntityInfoHelper { initSettings(clazz, entityInfo); // 初始化封装@Join父子类型注解信息 initJoin(clazz, globalConfig, entityInfo); - // 初始化knn插件配置 - entityInfo.setEnableKnnPlugin(globalConfig.getDbConfig().isEnableKnnPlugin()); // 放入缓存 ENTITY_INFO_CACHE.put(clazz, entityInfo); diff --git a/easy-es-springboot-test/src/main/java/org/dromara/easyes/test/entity/Document.java b/easy-es-springboot-test/src/main/java/org/dromara/easyes/test/entity/Document.java index 376f0aee..97ecbf87 100644 --- a/easy-es-springboot-test/src/main/java/org/dromara/easyes/test/entity/Document.java +++ b/easy-es-springboot-test/src/main/java/org/dromara/easyes/test/entity/Document.java @@ -154,8 +154,8 @@ public class Document extends BaseJoin { /** * 稠密向量类型,dims 非负 最大为2048 */ - @IndexField(fieldType = FieldType.DENSE_VECTOR, dims = 3, index = true) - private double[] myVectors; + @IndexField(fieldType = FieldType.DENSE_VECTOR, dims = 3) + private double[] vector; @IndexField(fieldType = FieldType.KEYWORD, index = false) private String indexFalse; diff --git a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/all/AllTest.java b/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/all/AllTest.java index 2955ce1a..bac72f3c 100644 --- a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/all/AllTest.java +++ b/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/all/AllTest.java @@ -86,7 +86,7 @@ public class AllTest { document.setMultiField("葡萄糖酸钙口服溶液"); document.setEnglish("Calcium Gluconate"); document.setBigNum(new BigDecimal("66.66")); - document.setMyVectors(new double[]{0.39684247970581666, 0.768707156181666, 0.5145490765571666}); + document.setVector(new double[]{0.39684247970581666, 0.768707156181666, 0.5145490765571666}); // System.out.println(JsonUtils.toJsonPrettyStr(document)); int successCount = documentMapper.insert(document); Assertions.assertEquals(successCount, 1); @@ -107,7 +107,7 @@ public class AllTest { Point point = new Point(13.400544 + i, 52.530286 + i); document.setGeoLocation(point.toString()); document.setStarNum(i); - document.setMyVectors(new double[]{35.89684247970581666, 86.268707156181666, 133.1145490765571666}); + document.setVector(new double[]{35.89684247970581666, 86.268707156181666, 133.1145490765571666}); // 针对个别数据 造一些差异项 方便测试不同场景 if (i == 2) { document.setLocation("40.17836693398477,116.64002551005981"); diff --git a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/KnnAndAnnTest.java b/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/KnnAndAnnTest.java deleted file mode 100644 index 8044b60b..00000000 --- a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/KnnAndAnnTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.dromara.easyes.test.vector; - -import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper; -import org.dromara.easyes.test.TestEasyEsApplication; -import org.dromara.easyes.test.entity.Document; -import org.dromara.easyes.test.mapper.DocumentMapper; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -import javax.annotation.Resource; -import java.util.List; - -/** - * @author lzh - * @date 25/09 - */ -@SpringBootTest(classes = TestEasyEsApplication.class) -public class KnnAndAnnTest { - @Resource - private DocumentMapper documentMapper; - - private final static String testDataId = "lzh-2025"; - - @Test - public void testCreateVectorIndex() { - documentMapper.createIndex(); - } - - @Test - public void testInsertVectorData() { - // 测试插入数据 - Document document = new Document(); - document.setEsId(testDataId); - document.setContent("测试插入向量数据"); - document.setMyVectors(new double[]{0.39684247970581055, 0.7687071561813354, 0.5145490765571594}); - int successCount = documentMapper.insert(document); - Assertions.assertEquals(1, successCount); - } - - @Test - public void testUpdateVectorData() { - // 测试插入数据 - Document document = new Document(); - document.setEsId(testDataId); - document.setContent("测试更新向量数据"); - document.setMyVectors(new double[]{0.39684247970581666, 0.768707156181666, 0.5145490765571666}); - int successCount = documentMapper.updateById(document); - Assertions.assertEquals(1, successCount); - } - - @Test - public void testknn() { - LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); - float[] queryVector = {0.39684247970581055f, 0.7687071561813354f, 0.5145490765571594f}; - wrapper.knn(Document::getMyVectors, queryVector, 10); - List documents = documentMapper.selectList(wrapper); - System.out.println(documents); - } - - @Test - public void testAnn() { - LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); - float[] queryVector = {0.39684247970581055f, 0.7687071561813354f, 0.5145490765571594f}; - wrapper.ann(Document::getMyVectors, queryVector, 10, 100); - List documents = documentMapper.selectList(wrapper); - System.out.println(documents); - } -} diff --git a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/VectorTest.java b/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/VectorTest.java index 6d7880ac..60760bec 100644 --- a/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/VectorTest.java +++ b/easy-es-springboot-test/src/test/java/org/dromara/easyes/test/vector/VectorTest.java @@ -32,7 +32,7 @@ public class VectorTest { Document document = new Document(); document.setEsId("35f6fff8-1d3b-48b6-a765-028ec81b1437"); document.setContent("测试插入数据"); - document.setMyVectors(new double[]{0.39684247970581055, 0.7687071561813354, 0.5145490765571594}); + document.setVector(new double[]{0.39684247970581055, 0.7687071561813354, 0.5145490765571594}); int successCount = documentMapper.insert(document); Assertions.assertEquals(1, successCount); } @@ -43,7 +43,7 @@ public class VectorTest { Document document = new Document(); document.setEsId("35f6fff8-1d3b-48b6-a765-028ec81b1437"); document.setContent("测试更新向量数据"); - document.setMyVectors(new double[]{0.39684247970581666, 0.768707156181666, 0.5145490765571666}); + document.setVector(new double[]{0.39684247970581666, 0.768707156181666, 0.5145490765571666}); int successCount = documentMapper.updateById(document); Assertions.assertEquals(1, successCount); } diff --git a/easy-es-springboot-test/src/test/resources/application.yml b/easy-es-springboot-test/src/test/resources/application.yml index 42c6be85..0a1adc36 100644 --- a/easy-es-springboot-test/src/test/resources/application.yml +++ b/easy-es-springboot-test/src/test/resources/application.yml @@ -2,9 +2,9 @@ easy-es: # enable: true address: 192.168.0.18:9200 compatible: true - schema: https - username: elastic - password: 1dcNTydUfH4GuN9549wj + # schema: http +# username: elastic +# password: mg123456 keep-alive-millis: 18000 global-config: i-kun-mode: false