Skip to content

Commit bd1332e

Browse files
anshlykovmp911de
authored andcommitted
DATAREDIS-729 - Add support for ZLEXCOUNT.
Original pull request: #569.
1 parent 4b33a62 commit bd1332e

21 files changed

+448
-0
lines changed

src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,24 @@ public Long zUnionStore(byte[] destKey, byte[]... sets) {
16591659
return convertAndReturn(delegate.zUnionStore(destKey, sets), identityConverter);
16601660
}
16611661

1662+
/*
1663+
* (non-Javadoc)
1664+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zLexCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
1665+
*/
1666+
@Override
1667+
public Long zLexCount(byte[] key, Range range) {
1668+
return delegate.zLexCount(key, range);
1669+
}
1670+
1671+
/*
1672+
* (non-Javadoc)
1673+
* @see org.springframework.data.redis.connection.StringRedisConnection#zLexCount(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Range)
1674+
*/
1675+
@Override
1676+
public Long zLexCount(String key, Range range) {
1677+
return delegate.zLexCount(serialize(key), range);
1678+
}
1679+
16621680
/*
16631681
* (non-Javadoc)
16641682
* @see org.springframework.data.redis.connection.RedisKeyCommands#pExpire(byte[], long)

src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
* @author Christoph Strobl
5656
* @author Mark Paluch
5757
* @author Tugdual Grall
58+
* @author Andrey Shlykov
5859
* @since 2.0
5960
*/
6061
public interface DefaultedRedisConnection extends RedisConnection {
@@ -1093,6 +1094,13 @@ default Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offse
10931094
return zSetCommands().zRangeByScore(key, min, max, offset, count);
10941095
}
10951096

1097+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1098+
@Override
1099+
@Deprecated
1100+
default Long zLexCount(byte[] key, Range range) {
1101+
return zSetCommands().zLexCount(key, range);
1102+
}
1103+
10961104
// HASH COMMANDS
10971105

10981106
/** @deprecated in favor of {@link RedisConnection#hashCommands()}}. */

src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
*
4747
* @author Christoph Strobl
4848
* @author Mark Paluch
49+
* @author Andrey Shlykov
4950
* @since 2.0
5051
*/
5152
public interface ReactiveZSetCommands {
@@ -1935,4 +1936,79 @@ default Flux<ByteBuffer> zRevRangeByLex(ByteBuffer key, Range<String> range, Lim
19351936
* @see <a href="https://redis.io/commands/zrevrangebylex">Redis Documentation: ZREVRANGEBYLEX</a>
19361937
*/
19371938
Flux<CommandResponse<ZRangeByLexCommand, Flux<ByteBuffer>>> zRangeByLex(Publisher<ZRangeByLexCommand> commands);
1939+
1940+
/**
1941+
* {@code ZLEXCOUNT} command parameters.
1942+
*
1943+
* @author Andrey Shlykov
1944+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
1945+
*/
1946+
class ZLexCountCommand extends KeyCommand {
1947+
1948+
private final Range<String> range;
1949+
1950+
private ZLexCountCommand(@Nullable ByteBuffer key, Range<String> range) {
1951+
super(key);
1952+
this.range = range;
1953+
}
1954+
1955+
/**
1956+
* Creates a new {@link ZLexCountCommand} given a {@link Range} of {@link String} to retrieve elements
1957+
* count.
1958+
*
1959+
* @param range must not be {@literal null}.
1960+
* @return a new {@link ZLexCountCommand} for {@link Range}.
1961+
*/
1962+
public static ZLexCountCommand stringsWithin(Range<String> range) {
1963+
1964+
Assert.notNull(range, "Range must not be null!");
1965+
1966+
return new ZLexCountCommand(null, range);
1967+
}
1968+
1969+
/**
1970+
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
1971+
*
1972+
* @param key must not be {@literal null}.
1973+
* @return a new {@link ZLexCountCommand} with {@literal key} applied.
1974+
*/
1975+
public ZLexCountCommand forKey(ByteBuffer key) {
1976+
1977+
Assert.notNull(key, "Key must not be null!");
1978+
1979+
return new ZLexCountCommand(key, range);
1980+
}
1981+
1982+
/**
1983+
* @return
1984+
*/
1985+
public Range<String> getRange() {
1986+
return range;
1987+
}
1988+
}
1989+
1990+
/**
1991+
* Count number of elements within sorted set with value within {@link Range}.
1992+
*
1993+
* @param key must not be {@literal null}.
1994+
* @param range must not be {@literal null}.
1995+
* @return
1996+
* @since 2.4
1997+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
1998+
*/
1999+
default Mono<Long> zLexCount(ByteBuffer key, Range<String> range) {
2000+
return zLexCount(Mono.just(ZLexCountCommand.stringsWithin(range).forKey(key))).next()
2001+
.map(NumericResponse::getOutput);
2002+
}
2003+
2004+
/**
2005+
* Count number of elements within sorted set with value within {@link Range}.
2006+
*
2007+
* @param commands must not be {@literal null}.
2008+
* @return
2009+
* @since 2.4
2010+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
2011+
*/
2012+
Flux<NumericResponse<ZLexCountCommand, Long>> zLexCount(Publisher<ZLexCountCommand> commands);
2013+
19382014
}

src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,4 +1059,16 @@ default Set<byte[]> zRevRangeByLex(byte[] key, Range range) {
10591059
@Nullable
10601060
Set<byte[]> zRevRangeByLex(byte[] key, Range range, Limit limit);
10611061

1062+
/**
1063+
* Count number of elements within sorted set with value between {@code Range#min} and {@code Range#max}.
1064+
*
1065+
* @param key must not be {@literal null}.
1066+
* @param range must not be {@literal null}.
1067+
* @return {@literal null} when used in pipeline / transaction.
1068+
* @since 2.4
1069+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
1070+
*/
1071+
@Nullable
1072+
Long zLexCount(byte[] key, Range range);
1073+
10621074
}

src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,19 @@ default Set<String> zRevRangeByLex(String key, Range range) {
15411541
*/
15421542
Set<String> zRevRangeByLex(String key, Range range, Limit limit);
15431543

1544+
/**
1545+
* Count number of elements within sorted set with value between {@code Range#min} and {@code Range#max}.
1546+
*
1547+
* @param key must not be {@literal null}.
1548+
* @param range must not be {@literal null}.
1549+
* @return {@literal null} when used in pipeline / transaction.
1550+
* @since 2.4
1551+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
1552+
* @see RedisZSetCommands#zLexCount(byte[], Range)
1553+
*/
1554+
@Nullable
1555+
Long zLexCount(String key, Range range);
1556+
15441557
// -------------------------------------------------------------------------
15451558
// Methods dealing with Redis Hashes
15461559
// -------------------------------------------------------------------------

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,26 @@ public Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset
795795
}
796796
}
797797

798+
/*
799+
* (non-Javadoc)
800+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zLexCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
801+
*/
802+
@Override
803+
public Long zLexCount(byte[] key, Range range) {
804+
805+
Assert.notNull(key, "Key must not be null!");
806+
Assert.notNull(range, "Range must not be null!");
807+
808+
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
809+
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
810+
811+
try {
812+
return connection.getCluster().zlexcount(key, min, max);
813+
} catch (Exception ex) {
814+
throw convertJedisAccessException(ex);
815+
}
816+
}
817+
798818
private DataAccessException convertJedisAccessException(Exception ex) {
799819
return connection.convertJedisAccessException(ex);
800820
}

src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,34 @@ public Set<byte[]> zRevRangeByLex(byte[] key, Range range, Limit limit) {
942942
}
943943
}
944944

945+
/*
946+
* (non-Javadoc)
947+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zLexCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
948+
*/
949+
@Override
950+
public Long zLexCount(byte[] key, Range range) {
951+
952+
Assert.notNull(key, "Key must not be null!");
953+
Assert.notNull(range, "Range must not be null!");
954+
955+
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
956+
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
957+
958+
try {
959+
if (isPipelined()) {
960+
pipeline(connection.newJedisResult(connection.getRequiredPipeline().zlexcount(key, min, max)));
961+
return null;
962+
}
963+
if (isQueueing()) {
964+
transaction(connection.newJedisResult(connection.getRequiredTransaction().zlexcount(key, min, max)));
965+
return null;
966+
}
967+
return connection.getJedis().zlexcount(key, min, max);
968+
} catch (Exception ex) {
969+
throw convertJedisAccessException(ex);
970+
}
971+
}
972+
945973
private boolean isPipelined() {
946974
return connection.isPipelined();
947975
}

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* @author Christoph Strobl
4646
* @author Mark Paluch
4747
* @author Michele Mancioppi
48+
* @author Andrey Shlykov
4849
* @since 2.0
4950
*/
5051
class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
@@ -484,6 +485,24 @@ public Flux<CommandResponse<ZRangeByLexCommand, Flux<ByteBuffer>>> zRangeByLex(
484485
}));
485486
}
486487

488+
/*
489+
* (non-Javadoc)
490+
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zLexCount(org.reactivestreams.Publisher)
491+
*/
492+
@Override
493+
public Flux<NumericResponse<ZLexCountCommand, Long>> zLexCount(Publisher<ZLexCountCommand> commands) {
494+
495+
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
496+
497+
Assert.notNull(command.getKey(), "Key must not be null!");
498+
Assert.notNull(command.getRange(), "Range must not be null!");
499+
500+
Mono<Long> result = cmd.zlexcount(command.getKey(), RangeConverter.toRange(command.getRange()));
501+
502+
return result.map(value -> new NumericResponse<>(command, value));
503+
}));
504+
}
505+
487506
private static ZStoreArgs zStoreArgs(@Nullable Aggregate aggregate, @Nullable List<Double> weights) {
488507

489508
ZStoreArgs args = new ZStoreArgs();

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,31 @@ public Set<byte[]> zRevRangeByLex(byte[] key, Range range, Limit limit) {
927927
}
928928
}
929929

930+
/*
931+
* (non-Javadoc)
932+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zLexCount(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
933+
*/
934+
@Override
935+
public Long zLexCount(byte[] key, Range range) {
936+
937+
Assert.notNull(key, "Key must not be null!");
938+
Assert.notNull(range, "Range must not be null!");
939+
940+
try {
941+
if (isPipelined()) {
942+
pipeline(connection.newLettuceResult(getAsyncConnection().zlexcount(key, LettuceConverters.toRange(range))));
943+
return null;
944+
}
945+
if (isQueueing()) {
946+
transaction(connection.newLettuceResult(getAsyncConnection().zlexcount(key, LettuceConverters.toRange(range))));
947+
return null;
948+
}
949+
return getConnection().zlexcount(key, LettuceConverters.toRange(range, true));
950+
} catch (Exception ex) {
951+
throw convertLettuceAccessException(ex);
952+
}
953+
}
954+
930955
private boolean isPipelined() {
931956
return connection.isPipelined();
932957
}

src/main/java/org/springframework/data/redis/core/BoundZSetOperations.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
* @author Christoph Strobl
3434
* @author Mark Paluch
3535
* @author Wongoo (望哥)
36+
* @author Andrey Shlykov
3637
*/
3738
public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
3839

@@ -414,6 +415,17 @@ default Set<V> reverseRangeByLex(Range range) {
414415
@Nullable
415416
Set<V> reverseRangeByLex(Range range, Limit limit);
416417

418+
/**
419+
* Count number of elements within sorted set with value between {@code Range#min} and {@code Range#max}.
420+
*
421+
* @param range must not be {@literal null}.
422+
* @return {@literal null} when used in pipeline / transaction.
423+
* @since 2.4
424+
* @see <a href="https://redis.io/commands/zlexcount">Redis Documentation: ZLEXCOUNT</a>
425+
*/
426+
@Nullable
427+
Long lexCount(Range range);
428+
417429
/**
418430
* @return never {@literal null}.
419431
*/

0 commit comments

Comments
 (0)