diff --git a/easy-es-common/src/main/java/cn/easyes/common/constants/BaseEsConstants.java b/easy-es-common/src/main/java/cn/easyes/common/constants/BaseEsConstants.java index b551e65e..5d395171 100644 --- a/easy-es-common/src/main/java/cn/easyes/common/constants/BaseEsConstants.java +++ b/easy-es-common/src/main/java/cn/easyes/common/constants/BaseEsConstants.java @@ -216,4 +216,16 @@ public interface BaseEsConstants { * keyword后缀 */ String KEYWORD_SUFFIX = ".keyword"; + /** + * 执行SQL x-pack 固定地址 + */ + String SQL_ENDPOINT = "/_xpack/sql?format=json"; + /** + * 执行DSL 查询固定地址 + */ + String DSL_ENDPOINT = "/_search"; + /** + * 查询 + */ + String QUERY = "query"; } diff --git a/easy-es-common/src/main/java/cn/easyes/common/enums/EsQueryTypeEnum.java b/easy-es-common/src/main/java/cn/easyes/common/enums/EsQueryTypeEnum.java index a7a8153c..92d5464a 100644 --- a/easy-es-common/src/main/java/cn/easyes/common/enums/EsQueryTypeEnum.java +++ b/easy-es-common/src/main/java/cn/easyes/common/enums/EsQueryTypeEnum.java @@ -100,7 +100,7 @@ public enum EsQueryTypeEnum { /** * 与条件必须满足,但不返回得分,效率更高 */ - FILTER, + AND_FILTER, /** * 或条件,相当于MYSQL中的OR 和MP中的or嵌套用法一致 */ @@ -110,7 +110,16 @@ public enum EsQueryTypeEnum { */ NESTED, /** - * 或条件,仅影响紧跟其后的一个条件,和MP中的拼接or用法一致 + * 拼接OR,或条件,和MP中的拼接or用法一致 */ - OR; + OR, + /** + * 拼接NOT,非条件 表示必须不满足 + */ + NOT, + /** + * 拼接filter, + */ + FILTER; + } diff --git a/easy-es-core/src/main/java/cn/easyes/core/conditions/function/Join.java b/easy-es-core/src/main/java/cn/easyes/core/conditions/function/Join.java index df4d99c5..4d0b53a3 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/conditions/function/Join.java +++ b/easy-es-core/src/main/java/cn/easyes/core/conditions/function/Join.java @@ -8,6 +8,28 @@ import java.io.Serializable; * Copyright © 2021 xpc1024 All Rights Reserved **/ public interface Join extends Serializable { + /** + * 拼接filter + * + * @return 泛型 + */ + default Children filter() { + return filter(true); + } + + /** + * 拼接filter + * + * @param condition 条件 + * @return 泛型 + */ + Children filter(boolean condition); + + /** + * 拼接or + * + * @return 泛型 + */ default Children or() { return or(true); } @@ -19,4 +41,21 @@ public interface Join extends Serializable { * @return 泛型 */ Children or(boolean condition); + + /** + * 拼接not + * + * @return 泛型 + */ + default Children not() { + return not(true); + } + + /** + * 拼接not + * + * @param condition 条件 + * @return 泛型 + */ + Children not(boolean condition); } diff --git a/easy-es-core/src/main/java/cn/easyes/core/config/GlobalConfig.java b/easy-es-core/src/main/java/cn/easyes/core/config/GlobalConfig.java index f661f81d..870ed9d0 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/config/GlobalConfig.java +++ b/easy-es-core/src/main/java/cn/easyes/core/config/GlobalConfig.java @@ -39,14 +39,14 @@ public class GlobalConfig { private boolean distributed = true; /** * Activate the current client's release index maximum number of retries - * 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数若数据量过大,重建索引数据迁移时间超过60*(180/60)=180分钟时,可调大此参数值,此参数值决定最大重试次数,超出此次数后仍未成功,则终止重试并记录异常日志 + * 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数,若数据量过大,重建索引数据迁移时间超过4320/60=72H,可调大此参数值,此参数值决定最大重试次数,超出此次数后仍未成功,则终止重试并记录异常日志 */ - private int activeReleaseIndexMaxRetry = 60; + private int activeReleaseIndexMaxRetry = 4320; /** * Activate the current client's release index retry delay for a fixed time uint:second - * 分布式环境下,平滑模式,当前客户端激活最新索引最大重试次数 若数据量过大,重建索引数据迁移时间超过60*(180/60)=180分钟时,可调大此参数值 此参数值决定多久重试一次 单位:秒 + * 分布式环境下,平滑模式,当前客户端激活最新索引重试时间间隔 若您期望最终一致性的时效性更高,可调小此值,但会牺牲一些性能 */ - private int activeReleaseIndexFixedDelay = 180; + private int activeReleaseIndexFixedDelay = 60; /** * es db config 数据库配置 */ @@ -61,7 +61,7 @@ public class GlobalConfig { /** * index prefix eg:daily_, 索引前缀 可缺省 */ - private String tablePrefix = EMPTY_STR; + private String indexPrefix = EMPTY_STR; /** * enable underscore to camel case default false 是否开启下划线自动转驼峰 默认关闭 */ diff --git a/easy-es-core/src/main/java/cn/easyes/core/core/AbstractChainWrapper.java b/easy-es-core/src/main/java/cn/easyes/core/core/AbstractChainWrapper.java index fe7db13c..f1b58173 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/core/AbstractChainWrapper.java +++ b/easy-es-core/src/main/java/cn/easyes/core/core/AbstractChainWrapper.java @@ -571,7 +571,19 @@ public abstract class AbstractChainWrapper consumer) { - return addNested(condition, FILTER, consumer); + return addNested(condition, AND_FILTER, consumer); + } + + @Override + public Children filter(boolean condition) { + return addParam(condition, FILTER, null, null, null); + } + + @Override + public Children not(boolean condition) { + return addParam(condition, NOT, null, null, null); } @Override @@ -667,8 +677,8 @@ public abstract class AbstractWrapper { Boolean refresh(String... indexNames); /** - * 执行静态dsl语句 不传索引名,默认为当前mapper对应索引 + * 执行SQL语句 * - * @param dsl dsl语句 - * @param method 请求类型 比如查询类GET 更新PUT... + * @param sql 被执行的sql语句 * @return 执行结果 jsonString */ - String executeDSL(String dsl, MethodEnum method); + String executeSQL(String sql); + + /** + * 执行静态dsl语句 不传索引名,默认为当前mapper对应索引 + * + * @param dsl dsl语句 + * @return 执行结果 jsonString + */ + String executeDSL(String dsl); /** * 执行静态dsl语句 可指定作用的索引 * * @param dsl dsl语句 - * @param method 请求类型 比如查询类GET 更新PUT... * @param indexName 作用的索引名 * @return 执行结果 jsonString */ - String executeDSL(String dsl, MethodEnum method, String indexName); + String executeDSL(String dsl, String indexName); /** * 标准查询 diff --git a/easy-es-core/src/main/java/cn/easyes/core/core/BaseEsMapperImpl.java b/easy-es-core/src/main/java/cn/easyes/core/core/BaseEsMapperImpl.java index 6258df35..062c72b5 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/core/BaseEsMapperImpl.java +++ b/easy-es-core/src/main/java/cn/easyes/core/core/BaseEsMapperImpl.java @@ -167,18 +167,26 @@ public class BaseEsMapperImpl implements BaseEsMapper { @Override @SneakyThrows - public String executeDSL(String dsl, MethodEnum method) { - String indexName = EntityInfoHelper.getEntityInfo(entityClass).getIndexName(); - Request request = new Request(method.toString(), indexName); + public String executeSQL(String sql) { + Request request = new Request(MethodEnum.POST.name(), SQL_ENDPOINT); + JSONObject jsonObject = new JSONObject(); + jsonObject.put(QUERY, sql); + request.setJsonEntity(jsonObject.toJSONString()); Response response = client.getLowLevelClient().performRequest(request); return EntityUtils.toString(response.getEntity()); } @Override @SneakyThrows - public String executeDSL(String dsl, MethodEnum method, String indexName) { + public String executeDSL(String dsl) { + return executeDSL(dsl, EntityInfoHelper.getEntityInfo(entityClass).getIndexName()); + } + + @Override + @SneakyThrows + public String executeDSL(String dsl, String indexName) { Assert.notNull(indexName, "indexName must not null"); - Request request = new Request(method.toString(), indexName); + Request request = new Request(MethodEnum.GET.name(), indexName + DSL_ENDPOINT); Response response = client.getLowLevelClient().performRequest(request); return EntityUtils.toString(response.getEntity()); } diff --git a/easy-es-core/src/main/java/cn/easyes/core/core/WrapperProcessor.java b/easy-es-core/src/main/java/cn/easyes/core/core/WrapperProcessor.java index d86542fe..d93ffd22 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/core/WrapperProcessor.java +++ b/easy-es-core/src/main/java/cn/easyes/core/core/WrapperProcessor.java @@ -98,7 +98,9 @@ public class WrapperProcessor { String realField; switch (param.getQueryTypeEnum()) { case OR: - // 渣男行为,*完就不认人了,因为拼接OR已处理过了 直接跳过 + case NOT: + case FILTER: + // 渣男行为,*完就不认人了,因为拼接类型在AbstractWrapper中已处理过了 直接跳过 break; case TERM: realField = getRealFieldAndSuffix(param.getColumn(), fieldTypeMap, mappingColumnMap); @@ -233,7 +235,7 @@ public class WrapperProcessor { break; // 下面五种嵌套类型 需要对孩子节点递归处理 case AND_MUST: - case FILTER: + case AND_FILTER: case MUST_NOT: case OR_SHOULD: queryBuilder = getBool(children, QueryBuilders.boolQuery(), entityInfo, null); @@ -264,12 +266,12 @@ public class WrapperProcessor { bool.must(queryBuilder); } else if (OR_SHOULD.equals(parentType)) { bool.should(queryBuilder); - } else if (FILTER.equals(parentType)) { + } else if (AND_FILTER.equals(parentType)) { bool.filter(queryBuilder); } else if (MUST_NOT.equals(parentType)) { bool.mustNot(queryBuilder); } else { - // just ignore,almost never happen + // by default bool.must(queryBuilder); } } diff --git a/easy-es-core/src/main/java/cn/easyes/core/toolkit/EntityInfoHelper.java b/easy-es-core/src/main/java/cn/easyes/core/toolkit/EntityInfoHelper.java index 3f63e397..ab3ab039 100644 --- a/easy-es-core/src/main/java/cn/easyes/core/toolkit/EntityInfoHelper.java +++ b/easy-es-core/src/main/java/cn/easyes/core/toolkit/EntityInfoHelper.java @@ -581,7 +581,7 @@ public class EntityInfoHelper { GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig(); IndexName table = clazz.getAnnotation(IndexName.class); String tableName = clazz.getSimpleName().toLowerCase(Locale.ROOT); - String tablePrefix = dbConfig.getTablePrefix(); + String tablePrefix = dbConfig.getIndexPrefix(); boolean tablePrefixEffect = true; String indexName; diff --git a/easy-es-test/src/main/java/cn/easyes/test/entity/Document.java b/easy-es-test/src/main/java/cn/easyes/test/entity/Document.java index 7b669cfe..31527735 100644 --- a/easy-es-test/src/main/java/cn/easyes/test/entity/Document.java +++ b/easy-es-test/src/main/java/cn/easyes/test/entity/Document.java @@ -14,7 +14,7 @@ import java.util.List; **/ @Data @Accessors(chain = true) -@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, childClass = Comment.class,routing = "666") +@IndexName(value = "easyes_document", shardsNum = 3, replicasNum = 2, keepGlobalPrefix = true, childClass = Comment.class,routing = "testRouting") public class Document { /** * es中的唯一id,字段名随便起,我这里演示用esId,你也可以用id(推荐),bizId等. diff --git a/easy-es-test/src/test/java/cn/easyes/test/all/AllTest.java b/easy-es-test/src/test/java/cn/easyes/test/all/AllTest.java index 4387d470..3363e31c 100644 --- a/easy-es-test/src/test/java/cn/easyes/test/all/AllTest.java +++ b/easy-es-test/src/test/java/cn/easyes/test/all/AllTest.java @@ -13,6 +13,7 @@ import cn.easyes.test.TestEasyEsApplication; import cn.easyes.test.entity.Document; import cn.easyes.test.mapper.DocumentMapper; import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.geo.GeoDistance; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.unit.DistanceUnit; @@ -29,6 +30,7 @@ import org.elasticsearch.search.aggregations.metrics.ParsedMin; import org.elasticsearch.search.aggregations.metrics.ParsedSum; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.GeoDistanceSortBuilder; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.junit.jupiter.api.*; @@ -161,6 +163,26 @@ public class AllTest { } // 3.查询 + + @Test + @Order(6) + public void testSQL() { + // 注意 sql中的from后面跟的是要被查询的索引名,也可以是索引别名(效果一样) 由于索引名可能会变,所以此处我采用别名ee_default_alias进行查询 + String sql = "select count(*) from ee_default_alias where star_num > 0"; + String jsonResult = documentMapper.executeSQL(sql); + System.out.println(jsonResult); + Assertions.assertNotNull(jsonResult); + } + + @Test + @Order(6) + public void testDSL() { + String dsl = "{\"size\":10000,\"query\":{\"bool\":{\"must\":[{\"term\":{\"title.keyword\":{\"value\":\"测试文档2\",\"boost\":1.0}}}],\"adjust_pure_negative\":true,\"boost\":1.0}}\"track_total_hits\":2147483647}"; + String jsonResult = documentMapper.executeDSL(dsl); + System.out.println(jsonResult); + Assertions.assertNotNull(jsonResult); + } + @Test @Order(6) public void testSelectOne() { @@ -491,6 +513,26 @@ public class AllTest { Assertions.assertEquals(2, documents.size()); } + @Test + @Order(6) + public void testConditionFilter() { + LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); + wrapper.eq(Document::getStarNum, 10) + .filter(i -> i.eq(Document::getTitle, "测试文档10")); + List documents = documentMapper.selectList(wrapper); + Assertions.assertEquals(1, documents.size()); + } + + @Test + @Order(6) + public void testConditionMustNot() { + LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); + wrapper.in(Document::getStarNum, 10,11,12,13) + .mustNot(i->i.eq(Document::getTitle,"测试文档10").eq(Document::getTitle,"测试文档11")); + List documents = documentMapper.selectList(wrapper); + Assertions.assertEquals(2, documents.size()); + } + @Test @Order(6) @@ -760,12 +802,12 @@ public class AllTest { LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); GeoPoint geoPoint = new GeoPoint(41.0, 116.0); wrapper.geoDistance(Document::getLocation, 168.8, DistanceUnit.KILOMETERS, geoPoint); -// GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort(FieldUtils.val(Document::getLocation), geoPoint) -// .unit(DistanceUnit.KILOMETERS) -// .geoDistance(GeoDistance.ARC) -// .order(SortOrder.DESC); -// -// wrapper.sort(geoDistanceSortBuilder); + GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort(FieldUtils.val(Document::getLocation), geoPoint) + .unit(DistanceUnit.KILOMETERS) + .geoDistance(GeoDistance.ARC) + .order(SortOrder.DESC); + + wrapper.sort(geoDistanceSortBuilder); List documents = documentMapper.selectList(wrapper); Assertions.assertEquals(4, documents.size()); } @@ -832,7 +874,7 @@ public class AllTest { @Test @Order(9) - public void testDSL() { + public void testComplex() { // SQL写法 // where business_type = 1 and (state = 9 or (state = 8 and bidding_sign = 1)) or business_type = 2 and state in (2,3) diff --git a/easy-es-test/src/test/java/cn/easyes/test/index/IndexTest.java b/easy-es-test/src/test/java/cn/easyes/test/index/IndexTest.java index 25b0f9d3..ffcf392d 100644 --- a/easy-es-test/src/test/java/cn/easyes/test/index/IndexTest.java +++ b/easy-es-test/src/test/java/cn/easyes/test/index/IndexTest.java @@ -14,6 +14,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.Map; @@ -126,4 +128,10 @@ public class IndexTest { boolean isOk = documentMapper.createIndex(wrapper); Assertions.assertTrue(isOk); } + + @Test + public void testActiveIndex(){ + String indexName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + documentMapper.setCurrentActiveIndex(indexName); + } } diff --git a/easy-es-test/src/test/java/cn/easyes/test/update/UpdateTest.java b/easy-es-test/src/test/java/cn/easyes/test/update/UpdateTest.java index c7504b42..14e70b28 100644 --- a/easy-es-test/src/test/java/cn/easyes/test/update/UpdateTest.java +++ b/easy-es-test/src/test/java/cn/easyes/test/update/UpdateTest.java @@ -51,7 +51,12 @@ public class UpdateTest { document2.setCustomField("乌拉巴拉中魔仙"); documentMapper.update(document2, wrapper); - // 关于case2 还有另一种省略实体的简单写法,这里不演示,后面章节有介绍,语法与MP一致 + // 关于case2 另一种省略实体的简单写法,语法与MP一致 + LambdaEsUpdateWrapper wrapper3 = new LambdaEsUpdateWrapper<>(); + wrapper3.eq(Document::getTitle, title1); + wrapper3.set(Document::getContent,"推*技术过软") + .set(Document::getCustomField,"乌拉巴拉中魔仙"); + documentMapper.update(null,wrapper); } @Test