diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java index d3a09813e3..f4da15df4e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java @@ -38,6 +38,8 @@ public class StringFilterPredicate implements SimpleKeyFilterPredicate { STARTS_WITH, ENDS_WITH, CONTAINS, - NOT_CONTAINS + NOT_CONTAINS, + IN, + NOT_IN } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index caed48758a..94645388b6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -537,6 +537,7 @@ public class EntityKeyMapping { value = value.toLowerCase(); operationField = String.format("lower(%s)", operationField); } + List values = new ArrayList<>(); switch (stringFilterPredicate.getOperation()) { case EQUAL: stringOperationQuery = String.format("%s = :%s)", operationField, paramName); @@ -560,8 +561,29 @@ public class EntityKeyMapping { value = "%" + value + "%"; stringOperationQuery = String.format("%s not like :%s or %s is null)", operationField, paramName, operationField); break; + case IN: + value = value.replaceAll("'","").replaceAll("\"", ""); + values = List.of(value.trim().split("\\s*,\\s*")); + System.out.println(value); + stringOperationQuery = String.format("%s in (:%s))", operationField, paramName); + break; + case NOT_IN: + value = value.replaceAll("'","").replaceAll("\"", ""); + values = List.of(value.trim().split("\\s*,\\s*")); + System.out.println(value); + stringOperationQuery = String.format("%s not in (:%s))", operationField, paramName); + } + switch (stringFilterPredicate.getOperation()) { + case IN: + case NOT_IN: + for (String str : values) { + System.out.println(str); + } + ctx.addStringListParameter(paramName, values); + break; + default: + ctx.addStringParameter(paramName, value); } - ctx.addStringParameter(paramName, value); return String.format("((%s is not null and %s)", field, stringOperationQuery); } diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index e504a3480d..535319e7c4 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -226,7 +226,9 @@ export enum StringOperation { STARTS_WITH = 'STARTS_WITH', ENDS_WITH = 'ENDS_WITH', CONTAINS = 'CONTAINS', - NOT_CONTAINS = 'NOT_CONTAINS' + NOT_CONTAINS = 'NOT_CONTAINS', + IN = 'CONTAINS', + NOT_IN = 'NOT_CONTAINS' } export const stringOperationTranslationMap = new Map( @@ -236,7 +238,9 @@ export const stringOperationTranslationMap = new Map( [StringOperation.STARTS_WITH, 'filter.operation.starts-with'], [StringOperation.ENDS_WITH, 'filter.operation.ends-with'], [StringOperation.CONTAINS, 'filter.operation.contains'], - [StringOperation.NOT_CONTAINS, 'filter.operation.not-contains'] + [StringOperation.NOT_CONTAINS, 'filter.operation.not-contains'], + [StringOperation.IN, 'filter.operation.in'], + [StringOperation.NOT_IN, 'filter.operation.not-in'] ] ); diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 5cd4a38065..4e8efca115 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2003,7 +2003,9 @@ "greater-or-equal": "greater or equal", "less-or-equal": "less or equal", "and": "and", - "or": "or" + "or": "or", + "in": "in", + "not-in": "not in" }, "ignore-case": "ignore case", "value": "Value",