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 a71b693794..b5dae9205a 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 7780b6337d..b48b48aa19 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 @@ public Long intersectAndStore(Collection otherKeys, K destKey) { 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 @@ public Long intersectAndStore(Collection otherKeys, K destKey, Aggregate aggr 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) */ @@ -187,20 +187,20 @@ public Set> reverseRangeWithScores(long start, long end) { /* * (non-Javadoc) - * @see org.springframework.data.redis.core.BoundZSetOperations#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range) + * @see org.springframework.data.redis.core.BoundZSetOperations#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) */ @Override - public Set rangeByLex(Range range) { - return rangeByLex(range, Limit.unlimited()); + public Set rangeByLex(Range range, Limit limit) { + return ops.rangeByLex(getKey(), range, limit); } /* * (non-Javadoc) - * @see org.springframework.data.redis.core.BoundZSetOperations#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) + * @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 rangeByLex(Range range, Limit limit) { - return ops.rangeByLex(getKey(), range, limit); + public Set reverseRangeByLex(Range range, Limit limit) { + return ops.reverseRangeByLex(getKey(), range, limit); } /* @@ -311,7 +311,7 @@ public Long unionAndStore(Collection otherKeys, K destKey) { 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 @@ public Long unionAndStore(Collection otherKeys, K destKey, Aggregate aggregat 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 07cff95ebf..c6bc37a6ef 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java @@ -166,22 +166,26 @@ public Set> reverseRangeWithScores(K key, long start, long end) { /* * (non-Javadoc) - * @see org.springframework.data.redis.core.ZSetOperations#rangeByLex(java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Range) + * @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) */ @Override - public Set rangeByLex(K key, Range range) { - return rangeByLex(key, range, Limit.unlimited()); + public Set rangeByLex(K key, Range range, Limit limit) { + + byte[] rawKey = rawKey(key); + Set rawValues = execute(connection -> connection.zRangeByLex(rawKey, range, limit), true); + + return deserializeValues(rawValues); } /* * (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) + * @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 rangeByLex(K key, Range range, Limit limit) { + public Set reverseRangeByLex(K key, Range range, Limit limit) { byte[] rawKey = rawKey(key); - Set rawValues = execute(connection -> connection.zRangeByLex(rawKey, range, limit), true); + Set rawValues = execute(connection -> connection.zRevRangeByLex(rawKey, range, limit), true); return deserializeValues(rawValues); } 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 df0518ee11..269b49b5e0 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 @@ default Long intersectAndStore(K key, Collection otherKeys, K destKey, Aggreg * @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 @@ default Long intersectAndStore(K key, Collection otherKeys, K destKey, Aggreg @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 eb4b1e920c..33b7205aa4 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 @@ -145,20 +145,20 @@ public Set reverseRange(long start, long end) { /* * (non-Javadoc) - * @see org.springframework.data.redis.support.collections.RedisZSet#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range) + * @see org.springframework.data.redis.support.collections.RedisZSet#rangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit) */ @Override - public Set rangeByLex(Range range) { - return boundZSetOps.rangeByLex(range); + public Set rangeByLex(Range range, Limit limit) { + return boundZSetOps.rangeByLex(range, limit); } /* * (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) + * @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 rangeByLex(Range range, Limit limit) { - return boundZSetOps.rangeByLex(range, limit); + public Set reverseRangeByLex(Range range, Limit limit) { + return boundZSetOps.reverseRangeByLex(range, limit); } /* 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 78f0bbcf8a..0e54e4376f 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 75d9cd890e..d40b848c30 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 void testRangeByLexUnboundedWithLimit() { 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 3d9949b916..ee881675bb 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 void testRangeByLexBoundedWithLimit() { 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();