diff --git a/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java b/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java index a71b69379..b5dae9205 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java @@ -368,7 +368,9 @@ public interface BoundZSetOperations extends BoundKeyOperations { * @see Redis Documentation: ZRANGEBYLEX */ @Nullable - Set rangeByLex(Range range); + default Set rangeByLex(Range range) { + return rangeByLex(range, Limit.unlimited()); + } /** * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at @@ -384,6 +386,34 @@ public interface BoundZSetOperations extends BoundKeyOperations { @Nullable Set rangeByLex(Range range, Limit limit); + /** + * Get all elements with reverse lexicographical ordering with a value between {@link Range#getMin()} and + * {@link Range#getMax()}. + * + * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 2.4 + * @see Redis Documentation: ZREVRANGEBYLEX + */ + @Nullable + default Set reverseRangeByLex(Range range) { + return reverseRangeByLex(range, Limit.unlimited()); + } + + /** + * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at + * {@link Limit#getOffset()} with reverse lexicographical ordering having a value between {@link Range#getMin()} and + * {@link Range#getMax()}. + * + * @param range must not be {@literal null}. + * @param limit can be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 2.4 + * @see Redis Documentation: ZREVRANGEBYLEX + */ + @Nullable + Set reverseRangeByLex(Range range, Limit limit); + /** * @return never {@literal null}. */ diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java index 7780b6337..b48b48aa1 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundZSetOperations.java @@ -104,7 +104,7 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.intersectAndStore(getKey(), otherKeys, destKey); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#intersectAndStore(java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate) */ @@ -113,7 +113,7 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.intersectAndStore(getKey(), otherKeys, destKey, aggregate); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#intersectAndStore(java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, org.springframework.data.redis.connection.RedisZSetCommands.Weights) */ @@ -185,15 +185,6 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.reverseRangeWithScores(getKey(), start, end); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.core.BoundZSetOperations#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range) - */ - @Override - public Set rangeByLex(Range range) { - return rangeByLex(range, Limit.unlimited()); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) @@ -203,6 +194,15 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.rangeByLex(getKey(), range, limit); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.BoundZSetOperations#reverseRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) + */ + @Override + public Set reverseRangeByLex(Range range, Limit limit) { + return ops.reverseRangeByLex(getKey(), range, limit); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#rank(java.lang.Object) @@ -311,7 +311,7 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.unionAndStore(getKey(), otherKeys, destKey); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#unionAndStore(java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate) */ @@ -320,7 +320,7 @@ class DefaultBoundZSetOperations extends DefaultBoundKeyOperations impl return ops.unionAndStore(getKey(), otherKeys, destKey, aggregate); } - /* + /* * (non-Javadoc) * @see org.springframework.data.redis.core.BoundZSetOperations#unionAndStore(java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, org.springframework.data.redis.connection.RedisZSetCommands.Weights) */ diff --git a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java index 07cff95eb..c6bc37a6e 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java @@ -164,15 +164,6 @@ class DefaultZSetOperations extends AbstractOperations implements ZS return deserializeTupleValues(rawValues); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.core.ZSetOperations#rangeByLex(java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Range) - */ - @Override - public Set rangeByLex(K key, Range range) { - return rangeByLex(key, range, Limit.unlimited()); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.core.ZSetOperations#rangeByLex(java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) @@ -186,6 +177,19 @@ class DefaultZSetOperations extends AbstractOperations implements ZS return deserializeValues(rawValues); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.ZSetOperations#reverseRangeByLex(java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) + */ + @Override + public Set reverseRangeByLex(K key, Range range, Limit limit) { + + byte[] rawKey = rawKey(key); + Set rawValues = execute(connection -> connection.zRevRangeByLex(rawKey, range, limit), true); + + return deserializeValues(rawValues); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.core.ZSetOperations#rangeByScore(java.lang.Object, double, double) diff --git a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java index df0518ee1..269b49b5e 100644 --- a/src/main/java/org/springframework/data/redis/core/ZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ZSetOperations.java @@ -475,7 +475,9 @@ public interface ZSetOperations { * @see Redis Documentation: ZRANGEBYLEX */ @Nullable - Set rangeByLex(K key, Range range); + default Set rangeByLex(K key, Range range) { + return rangeByLex(key, range, Limit.unlimited()); + } /** * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at @@ -492,6 +494,36 @@ public interface ZSetOperations { @Nullable Set rangeByLex(K key, Range range, Limit limit); + /** + * Get all elements with reverse lexicographical ordering from {@literal ZSET} at {@code key} with a value between + * {@link Range#getMin()} and {@link Range#getMax()}. + * + * @param key must not be {@literal null}. + * @param range must not be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 2.4 + * @see Redis Documentation: ZREVRANGEBYLEX + */ + @Nullable + default Set reverseRangeByLex(K key, Range range) { + return reverseRangeByLex(key, range, Limit.unlimited()); + } + + /** + * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at + * {@link Limit#getOffset()} with reverse lexicographical ordering from {@literal ZSET} at {@code key} with a value + * between {@link Range#getMin()} and {@link Range#getMax()}. + * + * @param key must not be {@literal null} + * @param range must not be {@literal null}. + * @param limit can be {@literal null}. + * @return {@literal null} when used in pipeline / transaction. + * @since 2.4 + * @see Redis Documentation: ZREVRANGEBYLEX + */ + @Nullable + Set reverseRangeByLex(K key, Range range, Limit limit); + /** * @return never {@literal null}. */ diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java index eb4b1e920..33b7205aa 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java @@ -143,15 +143,6 @@ public class DefaultRedisZSet extends AbstractRedisCollection implements R return boundZSetOps.reverseRange(start, end); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.support.collections.RedisZSet#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range) - */ - @Override - public Set rangeByLex(Range range) { - return boundZSetOps.rangeByLex(range); - } - /* * (non-Javadoc) * @see org.springframework.data.redis.support.collections.RedisZSet#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) @@ -161,6 +152,15 @@ public class DefaultRedisZSet extends AbstractRedisCollection implements R return boundZSetOps.rangeByLex(range, limit); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.support.collections.RedisZSet#reverseRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) + */ + @Override + public Set reverseRangeByLex(Range range, Limit limit) { + return boundZSetOps.reverseRangeByLex(range, limit); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.support.collections.RedisZSet#rangeByScore(double, double) diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisZSet.java b/src/main/java/org/springframework/data/redis/support/collections/RedisZSet.java index 78f0bbcf8..0e54e4376 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisZSet.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisZSet.java @@ -60,7 +60,9 @@ public interface RedisZSet extends RedisCollection, Set { * @see BoundZSetOperations#rangeByLex(Range) * @since 1.7 */ - Set rangeByLex(Range range); + default Set rangeByLex(Range range) { + return rangeByLex(range, Limit.unlimited()); + } /** * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at @@ -70,11 +72,37 @@ public interface RedisZSet extends RedisCollection, Set { * @param range must not be {@literal null}. * @param limit can be {@literal null}. * @return - * @see BoundZSetOperations#rangeByLex(Range, Limit) * @since 1.7 + * @see BoundZSetOperations#rangeByLex(Range, Limit) */ Set rangeByLex(Range range, Limit limit); + /** + * Get all elements with reverse lexicographical ordering with a value between {@link Range#getMin()} and + * {@link Range#getMax()}. + * + * @param range must not be {@literal null}. + * @return + * @since 2.4 + * @see BoundZSetOperations#reverseRangeByLex(Range) + */ + default Set reverseRangeByLex(Range range) { + return reverseRangeByLex(range, Limit.unlimited()); + } + + /** + * Get all elements {@literal n} elements, where {@literal n = } {@link Limit#getCount()}, starting at + * {@link Limit#getOffset()} with reverse lexicographical ordering having a value between {@link Range#getMin()} and + * {@link Range#getMax()}. + * + * @param range must not be {@literal null}. + * @param limit can be {@literal null}. + * @return + * @since 2.4 + * @see BoundZSetOperations#reverseRangeByLex(Range, Limit) + */ + Set reverseRangeByLex(Range range, Limit limit); + Set rangeByScore(double min, double max); Set reverseRangeByScore(double min, double max); diff --git a/src/test/java/org/springframework/data/redis/core/DefaultZSetOperationsTests.java b/src/test/java/org/springframework/data/redis/core/DefaultZSetOperationsTests.java index 75d9cd890..d40b848c3 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultZSetOperationsTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultZSetOperationsTests.java @@ -247,9 +247,29 @@ public class DefaultZSetOperationsTests { zSetOps.add(key, value2, 3.7); zSetOps.add(key, value3, 5.8); Set tuples = zSetOps.rangeByLex(key, RedisZSetCommands.Range.unbounded(), - RedisZSetCommands.Limit.limit().count(1).offset(1)); + RedisZSetCommands.Limit.limit().count(2).offset(1)); - assertThat(tuples).hasSize(1).startsWith(value2); + assertThat(tuples).hasSize(2).containsSequence(value2, value3); + } + + @Test // DATAREDIS-729 + public void testReverseRangeByLexUnboundedWithLimit() { + + assumeThat(valueFactory).isOfAnyClassIn(DoubleObjectFactory.class, DoubleAsStringObjectFactory.class, + LongAsStringObjectFactory.class, LongObjectFactory.class); + + K key = keyFactory.instance(); + V value1 = valueFactory.instance(); + V value2 = valueFactory.instance(); + V value3 = valueFactory.instance(); + + zSetOps.add(key, value1, 1.9); + zSetOps.add(key, value2, 3.7); + zSetOps.add(key, value3, 5.8); + Set tuples = zSetOps.reverseRangeByLex(key, RedisZSetCommands.Range.unbounded(), + RedisZSetCommands.Limit.limit().count(2).offset(1)); + + assertThat(tuples).hasSize(2).containsSequence(value2, value1); } @Test // DATAREDIS-407 diff --git a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisZSetTest.java b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisZSetTest.java index 3d9949b91..ee881675b 100644 --- a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisZSetTest.java +++ b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisZSetTest.java @@ -402,14 +402,31 @@ public abstract class AbstractRedisZSetTest extends AbstractRedisCollectionTe zSet.add(t2, 2); zSet.add(t3, 3); Set tuples = zSet.rangeByLex(RedisZSetCommands.Range.range().gte(t1), - RedisZSetCommands.Limit.limit().count(1).offset(1)); + RedisZSetCommands.Limit.limit().count(2).offset(1)); - assertThat(tuples.size()).isEqualTo(1); - T tuple = tuples.iterator().next(); - assertThat(tuple).isEqualTo(t2); + assertThat(tuples).hasSize(2).containsSequence(t2, t3); } - @Test + @Test // DATAREDIS-729 + public void testReverseRangeByLexBoundedWithLimit() { + + assumeThat(factory).isOfAnyClassIn(DoubleObjectFactory.class, DoubleAsStringObjectFactory.class, + LongAsStringObjectFactory.class, LongObjectFactory.class); + + T t1 = getT(); + T t2 = getT(); + T t3 = getT(); + + zSet.add(t1, 1); + zSet.add(t2, 2); + zSet.add(t3, 3); + Set tuples = zSet.reverseRangeByLex(RedisZSetCommands.Range.range().gte(t1), + RedisZSetCommands.Limit.limit().count(2).offset(1)); + + assertThat(tuples).hasSize(2).containsSequence(t2, t1); + } + + @Test // DATAREDIS-729 public void testReverseRangeByScore() { T t1 = getT();