diff --git a/src/main/java/org/springframework/data/aerospike/query/FilterOperation.java b/src/main/java/org/springframework/data/aerospike/query/FilterOperation.java index 7f29e4ca2..12ac9a620 100644 --- a/src/main/java/org/springframework/data/aerospike/query/FilterOperation.java +++ b/src/main/java/org/springframework/data/aerospike/query/FilterOperation.java @@ -58,6 +58,9 @@ import static org.springframework.data.aerospike.util.Utils.getValueExpOrFail; public enum FilterOperation { + /** + * Conjunction of two or more Qualifiers using logical AND. + */ AND { @Override public Exp filterExp(Map qualifierMap) { @@ -83,6 +86,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * Conjunction of two or more Qualifiers using logical OR. + */ OR { @Override public Exp filterExp(Map qualifierMap) { @@ -108,6 +114,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find by <...> in a given Collection". + */ IN { @Override public Exp filterExp(Map qualifierMap) { @@ -132,6 +141,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find by <...> not in a given Collection". + */ NOT_IN { @Override public Exp filterExp(Map qualifierMap) { @@ -156,6 +168,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find by <...> equals a given object". + */ EQ { @Override public Exp filterExp(Map qualifierMap) { @@ -200,6 +215,9 @@ public Filter sIndexFilter(Map qualifierMap) { }; } }, + /** + * For use in queries "find by <...> not equal to a given object". + */ NOTEQ { @Override public Exp filterExp(Map qualifierMap) { @@ -241,6 +259,10 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // not supported in the secondary index filter } }, + /** + * For use in queries "find by <...> greater than a given object". + * Information about ordering. + */ GT { @Override public Exp filterExp(Map qualifierMap) { @@ -269,6 +291,10 @@ public Filter sIndexFilter(Map qualifierMap) { return Filter.range(getBinName(qualifierMap), getValue(qualifierMap).toLong() + 1, Long.MAX_VALUE); } }, + /** + * For use in queries "find by <...> greater than a given object or equal to it". + * Information about ordering. + */ GTEQ { @Override public Exp filterExp(Map qualifierMap) { @@ -295,6 +321,10 @@ public Filter sIndexFilter(Map qualifierMap) { return Filter.range(getBinName(qualifierMap), getValue(qualifierMap).toLong(), Long.MAX_VALUE); } }, + /** + * For use in queries "find by <...> less than a given object". + * Information about ordering. + */ LT { @Override public Exp filterExp(Map qualifierMap) { @@ -322,6 +352,10 @@ public Filter sIndexFilter(Map qualifierMap) { return Filter.range(getBinName(qualifierMap), Long.MIN_VALUE, getValue(qualifierMap).toLong() - 1); } }, + /** + * For use in queries "find by <...> less than a given object or equal to it". + * Information about ordering. + */ LTEQ { @Override public Exp filterExp(Map qualifierMap) { @@ -348,6 +382,10 @@ public Filter sIndexFilter(Map qualifierMap) { return Filter.range(getBinName(qualifierMap), Long.MIN_VALUE, getValue(qualifierMap).toLong()); } }, + /** + * For use in queries "find by <...> between two given objects". + * Information about ordering. + */ BETWEEN { @Override public Exp filterExp(Map qualifierMap) { @@ -388,6 +426,9 @@ public Filter sIndexFilter(Map qualifierMap) { getSecondValue(qualifierMap).toLong()); } }, + /** + * For use in queries "find by <...> starts with a given String". + */ STARTS_WITH { @Override public Exp filterExp(Map qualifierMap) { @@ -400,6 +441,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "starts with" queries } }, + /** + * For use in queries "find by <...> ends with a given String". + */ ENDS_WITH { @Override public Exp filterExp(Map qualifierMap) { @@ -412,6 +456,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "ends with" queries } }, + /** + * For use in queries "find by <...> containing a given object". + */ CONTAINING { @Override public Exp filterExp(Map qualifierMap) { @@ -425,6 +472,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "contains" queries } }, + /** + * For use in queries "find by <...> not containing a given object". + */ NOT_CONTAINING { @Override public Exp filterExp(Map qualifierMap) { @@ -439,6 +489,9 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "contains" queries } }, + /** + * For use in queries "find by <...> like a given String". + */ LIKE { @Override public Exp filterExp(Map qualifierMap) { @@ -454,6 +507,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // not supported } }, + /** + * For use in queries "find records where Map key <...> has value equal to a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_EQ_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -480,6 +540,13 @@ public Filter sIndexFilter(Map qualifierMap) { }; } }, + /** + * For use in queries "find records where Map key <...> has value not equal to a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_NOTEQ_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -491,6 +558,14 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // not supported } }, + /** + * For use in queries "find records where Map key <...> has value equal to one of the objects in a given + * Collection". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_IN_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -517,6 +592,14 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where Map key <...> has value equal to neither of the objects in a given + * Collection". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_NOT_IN_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -542,6 +625,14 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where Map key <...> has value greater than a given object". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_GT_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -563,6 +654,14 @@ public Filter sIndexFilter(Map qualifierMap) { Long.MAX_VALUE, getCtxArr(qualifierMap)); } }, + /** + * For use in queries "find records where Map key <...> has value greater than a given object or equal to it". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_GTEQ_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -581,6 +680,14 @@ public Filter sIndexFilter(Map qualifierMap) { getKey(qualifierMap).toLong(), Long.MAX_VALUE, getCtxArr(qualifierMap)); } }, + /** + * For use in queries "find records where Map key <...> has value less than a given object". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_LT_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -600,6 +707,14 @@ public Filter sIndexFilter(Map qualifierMap) { getKey(qualifierMap).toLong() - 1, getCtxArr(qualifierMap)); } }, + /** + * For use in queries "find records where Map key <...> has value less than a given object or equal to it". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_LTEQ_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -618,6 +733,14 @@ public Filter sIndexFilter(Map qualifierMap) { getValue(qualifierMap).toLong(), getCtxArr(qualifierMap)); } }, + /** + * For use in queries "find records where Map key <...> has value between two given objects". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_BETWEEN_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -667,6 +790,13 @@ public Filter sIndexFilter(Map qualifierMap) { getCtxArr(qualifierMap)); } }, + /** + * For use in queries "find records where Map key <...> has value that starts with a given String". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_STARTS_WITH_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -683,6 +813,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "starts with" queries } }, + /** + * For use in queries "find records where Map key <...> has value that is like a given String". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_LIKE_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -701,6 +838,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // not supported } }, + /** + * For use in queries "find records where Map key <...> has value that ends with a given String". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_ENDS_WITH_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -717,6 +861,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "ends with" queries } }, + /** + * For use in queries "find records where Map key <...> has value that contains a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_CONTAINING_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -763,6 +914,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "contains" queries } }, + /** + * For use in queries "find records where Map key <...> does not have value that contains a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_NOT_CONTAINING_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -814,6 +972,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // String secondary index does not support "contains" queries } }, + /** + * For use in queries "find records where Map key <...> has existing value". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_EXISTS_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -825,6 +990,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where Map key <...> does not have existing value". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_NOT_EXISTS_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -836,6 +1008,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where Map key <...> has value that is not null (i.e. exists)". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_IS_NOT_NULL_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -856,6 +1035,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where Map key <...> has value that is null (i.e. does not exist)". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_IS_NULL_BY_KEY { @Override public Exp filterExp(Map qualifierMap) { @@ -876,6 +1062,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; } }, + /** + * For use in queries "find records where keys of Map <...> contain a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_KEYS_CONTAIN { @Override public Exp filterExp(Map qualifierMap) { @@ -887,6 +1080,13 @@ public Filter sIndexFilter(Map qualifierMap) { return collectionContains(IndexCollectionType.MAPKEYS, qualifierMap); } }, + /** + * For use in queries "find records where keys of Map <...> do not contain a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_KEYS_NOT_CONTAIN { @Override public Exp filterExp(Map qualifierMap) { @@ -898,6 +1098,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // currently not supported } }, + /** + * For use in queries "find records where values of Map <...> contain a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VALUES_CONTAIN { @Override public Exp filterExp(Map qualifierMap) { @@ -909,6 +1116,13 @@ public Filter sIndexFilter(Map qualifierMap) { return collectionContains(IndexCollectionType.MAPVALUES, qualifierMap); } }, + /** + * For use in queries "find records where values of Map <...> do not contain a given object". + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VALUES_NOT_CONTAIN { @Override public Exp filterExp(Map qualifierMap) { @@ -920,6 +1134,14 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // currently not supported } }, + /** + * For use in queries "find records where keys of Map <...> are between two given objects". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_KEYS_BETWEEN { @Override public Exp filterExp(Map qualifierMap) { @@ -948,6 +1170,14 @@ public Filter sIndexFilter(Map qualifierMap) { return collectionRange(IndexCollectionType.MAPKEYS, qualifierMap); } }, + /** + * For use in queries "find records where values of Map <...> are between two given objects". + * Information about ordering. + *
+ * Map can be a whole bin or a part of it (nested inside one or more Lists or other Maps). + *
+ * Maps in Aerospike DB represent not only Java Maps, but also POJOs. + */ MAP_VAL_BETWEEN { @Override public Exp filterExp(Map qualifierMap) { @@ -979,6 +1209,9 @@ public Filter sIndexFilter(Map qualifierMap) { return collectionRange(IndexCollectionType.MAPVALUES, qualifierMap); } }, + /** + * For use in queries "find by Geo <...> within a given GeoJSON". + */ GEO_WITHIN { @Override public Exp filterExp(Map qualifierMap) { @@ -990,6 +1223,10 @@ public Filter sIndexFilter(Map qualifierMap) { return geoWithinRadius(IndexCollectionType.DEFAULT, qualifierMap); } }, + /** + * For use in queries "find by Collection <...> containing a given object". The Collection can be a whole bin or + * part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_CONTAINING { @Override public Exp filterExp(Map qualifierMap) { @@ -1016,6 +1253,10 @@ public Filter sIndexFilter(Map qualifierMap) { return collectionContains(IndexCollectionType.LIST, qualifierMap); } }, + /** + * For use in queries "find by Collection <...> not containing a given object". The Collection can be a whole bin or + * part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_NOT_CONTAINING { @Override public Exp filterExp(Map qualifierMap) { @@ -1041,38 +1282,13 @@ public Filter sIndexFilter(Map qualifierMap) { return null; // currently not supported } }, - COLLECTION_VAL_BETWEEN { - @Override - public Exp filterExp(Map qualifierMap) { - Pair twoValues = switch (getValue(qualifierMap).getType()) { - case INTEGER -> - Pair.of(Exp.val(getValue(qualifierMap).toLong()), Exp.val(getSecondValue(qualifierMap).toLong())); - case STRING -> Pair.of(Exp.val(getValue(qualifierMap).toString()), - Exp.val(getSecondValue(qualifierMap).toString())); - case LIST -> Pair.of(Exp.val((List) getValue(qualifierMap).getObject()), - Exp.val((List) getSecondValue(qualifierMap).getObject())); - case MAP -> Pair.of(Exp.val((Map) getValue(qualifierMap).getObject()), - Exp.val((Map) getSecondValue(qualifierMap).getObject())); - default -> throw new UnsupportedOperationException( - "COLLECTION_VAL_BETWEEN FilterExpression unsupported type: got " - + getValue(qualifierMap).getClass().getSimpleName()); - }; - return Exp.gt( - ListExp.getByValueRange(ListReturnType.COUNT, twoValues.getFirst(), twoValues.getSecond(), - Exp.listBin(getBinName(qualifierMap))), - Exp.val(0)); - } - - @Override - public Filter sIndexFilter(Map qualifierMap) { - if (getValue(qualifierMap).getType() != INTEGER || getSecondValue(qualifierMap).getType() != INTEGER) { - return null; - } - - return collectionRange(IndexCollectionType.LIST, qualifierMap); // both limits are inclusive - } - }, + /** + * For use in queries "find records where Collection <...> contains values greater than a given object". + * Information about ordering. + *
+ * The Collection can be a whole bin or a part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_GT { @Override public Exp filterExp(Map qualifierMap) { @@ -1116,6 +1332,13 @@ public Filter sIndexFilter(Map qualifierMap) { getValue(qualifierMap).toLong() + 1, Long.MAX_VALUE); } }, + /** + * For use in queries "find records where Collection <...> contains values greater than a given object or equal to + * it". + * Information about ordering. + *
+ * The Collection can be a whole bin or a part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_GTEQ { @Override public Exp filterExp(Map qualifierMap) { @@ -1144,6 +1367,12 @@ public Filter sIndexFilter(Map qualifierMap) { Long.MAX_VALUE); } }, + /** + * For use in queries "find records where Collection <...> contains values less than a given object". + * Information about ordering. + *
+ * The Collection can be a whole bin or a part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_LT { @Override public Exp filterExp(Map qualifierMap) { @@ -1181,6 +1410,13 @@ public Filter sIndexFilter(Map qualifierMap) { getValue(qualifierMap).toLong() - 1); } }, + /** + * For use in queries "find records where Collection <...> contains values less than a given object or equal to + * it". + * Information about ordering. + *
+ * The Collection can be a whole bin or a part of it (nested inside one or more Lists or Maps). + */ COLLECTION_VAL_LTEQ { @Override public Exp filterExp(Map qualifierMap) { @@ -1222,7 +1458,49 @@ public Filter sIndexFilter(Map qualifierMap) { return Filter.range(getBinName(qualifierMap), IndexCollectionType.LIST, Long.MIN_VALUE, getValue(qualifierMap).toLong()); } - }, IS_NOT_NULL { + }, + /** + * For use in queries "find records where Collection <...> contains values between two given objects". + * Information about ordering. + *
+ * The Collection can be a whole bin or a part of it (nested inside one or more Lists or Maps). + */ + COLLECTION_VAL_BETWEEN { + @Override + public Exp filterExp(Map qualifierMap) { + Pair twoValues = switch (getValue(qualifierMap).getType()) { + case INTEGER -> + Pair.of(Exp.val(getValue(qualifierMap).toLong()), Exp.val(getSecondValue(qualifierMap).toLong())); + case STRING -> Pair.of(Exp.val(getValue(qualifierMap).toString()), + Exp.val(getSecondValue(qualifierMap).toString())); + case LIST -> Pair.of(Exp.val((List) getValue(qualifierMap).getObject()), + Exp.val((List) getSecondValue(qualifierMap).getObject())); + case MAP -> Pair.of(Exp.val((Map) getValue(qualifierMap).getObject()), + Exp.val((Map) getSecondValue(qualifierMap).getObject())); + default -> throw new UnsupportedOperationException( + "COLLECTION_VAL_BETWEEN FilterExpression unsupported type: got " + + getValue(qualifierMap).getClass().getSimpleName()); + }; + + return Exp.gt( + ListExp.getByValueRange(ListReturnType.COUNT, twoValues.getFirst(), twoValues.getSecond(), + Exp.listBin(getBinName(qualifierMap))), + Exp.val(0)); + } + + @Override + public Filter sIndexFilter(Map qualifierMap) { + if (getValue(qualifierMap).getType() != INTEGER || getSecondValue(qualifierMap).getType() != INTEGER) { + return null; + } + + return collectionRange(IndexCollectionType.LIST, qualifierMap); // both limits are inclusive + } + }, + /** + * For use in queries "find records where <...> is not null (i.e. exists)". + */ + IS_NOT_NULL { @Override public Exp filterExp(Map qualifierMap) { return Exp.binExists(getBinName(qualifierMap)); @@ -1232,7 +1510,11 @@ public Exp filterExp(Map qualifierMap) { public Filter sIndexFilter(Map qualifierMap) { return null; } - }, IS_NULL { + }, + /** + * For use in queries "find records where <...> is null (i.e. does not exist)". + */ + IS_NULL { @Override public Exp filterExp(Map qualifierMap) { // with value set to null a bin becomes non-existing @@ -1260,7 +1542,7 @@ public Filter sIndexFilter(Map qualifierMap) { */ protected static final List dualFilterOperations = Arrays.asList( MAP_VAL_EQ_BY_KEY, MAP_VAL_GT_BY_KEY, MAP_VAL_GTEQ_BY_KEY, MAP_VAL_LT_BY_KEY, MAP_VAL_LTEQ_BY_KEY, - MAP_VAL_BETWEEN_BY_KEY + MAP_VAL_BETWEEN_BY_KEY, MAP_KEYS_BETWEEN, MAP_VAL_BETWEEN ); @SuppressWarnings("unchecked") diff --git a/src/main/java/org/springframework/data/aerospike/query/StatementBuilder.java b/src/main/java/org/springframework/data/aerospike/query/StatementBuilder.java index 20754b6d5..e22c9eccb 100644 --- a/src/main/java/org/springframework/data/aerospike/query/StatementBuilder.java +++ b/src/main/java/org/springframework/data/aerospike/query/StatementBuilder.java @@ -140,7 +140,7 @@ private boolean isIndexedBin(Statement stmt, Qualifier qualifier) { } if (log.isDebugEnabled() && hasField) { - log.debug("Query #{}, bin {}.{}.{} has secondary index: {}", + log.debug("Qualifier #{}, bin {}.{}.{} has secondary index: {}", qualifier.hashCode(), stmt.getNamespace(), stmt.getSetName(), qualifier.getBinName(), hasIndex); } return hasIndex; diff --git a/src/main/java/org/springframework/data/aerospike/util/Utils.java b/src/main/java/org/springframework/data/aerospike/util/Utils.java index 757338507..cac9dec68 100644 --- a/src/main/java/org/springframework/data/aerospike/util/Utils.java +++ b/src/main/java/org/springframework/data/aerospike/util/Utils.java @@ -24,6 +24,7 @@ import com.aerospike.client.cluster.Node; import com.aerospike.client.command.ParticleType; import com.aerospike.client.exp.Exp; +import lombok.NonNull; import lombok.experimental.UtilityClass; import org.slf4j.Logger; import org.springframework.dao.InvalidDataAccessResourceUsageException; @@ -195,12 +196,12 @@ public static void logQualifierDetails(CriteriaDefinition criteria, Logger logge String values = ""; String value = valueToString(qualifier.getValue()); String value2 = valueToString(qualifier.getSecondValue()); - values = hasLength(value) ? String.format("value = %s", value) : ""; + values = hasLength(value) ? String.format(", value = %s", value) : ""; values = hasLength(value2) ? String.format("%s, value2 = %s", values, value2) : values; String path = ""; if (isBinQualifier(qualifier)) { // bin qualifier - path = (hasLength(qualifier.getBinName()) ? qualifier.getBinName() : ""); + path = (hasLength(qualifier.getBinName()) ? String.format(" path = %s,", qualifier.getBinName()) : ""); if (qualifier.getCtxArray() != null && qualifier.getCtxArray().length > 0) { path += "." + ctxArrToString(qualifier.getCtxArray()); } @@ -211,7 +212,18 @@ public static void logQualifierDetails(CriteriaDefinition criteria, Logger logge path = qualifier.getMetadataField().toString(); } - logger.debug("Created query #{}: path = {}, operation = {}, {}", qualifier.hashCode(), path, operation, values); + String qualifiersStr = (qualifier.getQualifiers() != null && qualifier.getQualifiers().length > 0) + ? String.format(", qualifiers = %s,", qualifiersHashesToString(qualifier.getQualifiers())) + : ""; + + logger.debug("Created qualifier #{}:{} operation = {}{}{}", qualifier.hashCode(), path, operation, values, + qualifiersStr); + } + + private static String qualifiersHashesToString(@NonNull Qualifier[] qualifiers) { + return "[" + String.join(",", + Arrays.stream(qualifiers).map(qualifier -> String.valueOf(qualifier.hashCode())).toList()) + + "]"; } private static boolean isBinQualifier(Qualifier qualifier) { diff --git a/src/test/java/org/springframework/data/aerospike/repository/query/blocking/indexed/findBy/CustomQueriesTests.java b/src/test/java/org/springframework/data/aerospike/repository/query/blocking/indexed/findBy/CustomQueriesTests.java index b2421477f..c2d167cdd 100644 --- a/src/test/java/org/springframework/data/aerospike/repository/query/blocking/indexed/findBy/CustomQueriesTests.java +++ b/src/test/java/org/springframework/data/aerospike/repository/query/blocking/indexed/findBy/CustomQueriesTests.java @@ -29,9 +29,9 @@ void findByNestedSimpleProperty_String_map_in_map() { Qualifier nestedZipCodeEq = Qualifier.builder() // find records having a nested map with a key that equals a value // POJOs are saved as Maps - .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // POJOs are saved as Maps + .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // where address's key 'zipCode' has value "C0123" .setPath("friend.address.zipCode") // path includes bin name, context and the required map key - .setValue(Value.get(zipCode)) // value of the nested key + .setValue(zipCode) // value of the nested key .build(); assertQueryHasSecIndexFilter(new Query(nestedZipCodeEq), IndexedPerson.class); @@ -51,7 +51,7 @@ void findByNestedSimpleProperty_String_map_in_list() { Qualifier nestedZipCodeEq = Qualifier.builder() // find records having a nested map with a key that equals a value // POJOs are saved as Maps - .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) + .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // where list element 'zipCode' has value "ZipCode" .setPath("addressesList.[0].zipCode") // path: bin name, context (list index) and the required map key .setValue(Value.get(zipCode)) // value of the nested key .build(); @@ -77,7 +77,7 @@ void findByNestedSimpleProperty_String_3_levels() { Qualifier nestedZipCodeEq = Qualifier.builder() // find records having a nested map with a key that equals a value // POJOs are saved as Maps - .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // POJOs are saved as Maps + .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // where address's key 'zipCode' has value "C0123" .setPath("friend.bestFriend.address.zipCode") // path includes bin name, context and the required map key .setValue(Value.get(zipCode)) // value of the nested key .build(); @@ -99,7 +99,7 @@ void findByNestedSimpleProperty_Integer_3_levels() { repository.save(peter); Qualifier nestedApartmentEq = Qualifier.builder() - .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // POJOs are saved as Maps + .setFilterOperation(FilterOperation.MAP_VAL_EQ_BY_KEY) // where address's key 'apartment' has value 1 .setPath("friend.bestFriend.address.apartment") // path includes bin name, context and the required map key .setValue(Value.get(apartment)) // value of the nested key .build(); @@ -125,7 +125,8 @@ void findByNestedSimplePropertyBetween_Integer_3_levels() { Qualifier nestedApartmentBetween = Qualifier.builder() // find records having a map with a key between given values // POJOs are saved as Maps - .setFilterOperation(FilterOperation.MAP_VAL_BETWEEN_BY_KEY) // POJOs are saved as Maps + // where address's key 'apartment' has value between 1 and 3 + .setFilterOperation(FilterOperation.MAP_VAL_BETWEEN_BY_KEY) .setPath("bestFriend.friend.address.apartment") // path includes bin name, context and the required map key .setValue(Value.get(1)) // lower limit for the value of the nested key .setSecondValue(Value.get(3)) // lower limit for the value of the nested key