Skip to content

Commit 8d3d412

Browse files
committed
Add WITHSCORE option to ZRANK and ZREVRANK commands
Close #3178 Signed-off-by: kshired <[email protected]>
1 parent 2be9ce2 commit 8d3d412

28 files changed

+690
-8
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.springframework.data.redis.connection.stream.StringRecord;
5252
import org.springframework.data.redis.connection.zset.Aggregate;
5353
import org.springframework.data.redis.connection.zset.DefaultTuple;
54+
import org.springframework.data.redis.connection.zset.RankAndScore;
5455
import org.springframework.data.redis.connection.zset.Tuple;
5556
import org.springframework.data.redis.connection.zset.Weights;
5657
import org.springframework.data.redis.core.ConvertingCursor;
@@ -81,6 +82,7 @@
8182
* @author ihaohong
8283
* @author Dennis Neufeld
8384
* @author Shyngys Sapraliyev
85+
* @author Seongil Kim
8486
*/
8587
@NullUnmarked
8688
@SuppressWarnings({ "ConstantConditions", "deprecation" })
@@ -1181,6 +1183,11 @@ public Long zRank(byte[] key, byte[] value) {
11811183
return convertAndReturn(delegate.zRank(key, value), Converters.identityConverter());
11821184
}
11831185

1186+
@Override
1187+
public RankAndScore zRankWithScore(byte[] key, byte[] value) {
1188+
return convertAndReturn(delegate.zRankWithScore(key, value), Converters.identityConverter());
1189+
}
1190+
11841191
@Override
11851192
public Long zRem(byte[] key, byte[]... values) {
11861193
return convertAndReturn(delegate.zRem(key, values), Converters.identityConverter());
@@ -1221,6 +1228,11 @@ public Long zRevRank(byte[] key, byte[] value) {
12211228
return convertAndReturn(delegate.zRevRank(key, value), Converters.identityConverter());
12221229
}
12231230

1231+
@Override
1232+
public RankAndScore zRevRankWithScore(byte[] key, byte[] value) {
1233+
return convertAndReturn(delegate.zRevRankWithScore(key, value), Converters.identityConverter());
1234+
}
1235+
12241236
@Override
12251237
public Double zScore(byte[] key, byte[] value) {
12261238
return convertAndReturn(delegate.zScore(key, value), Converters.identityConverter());
@@ -2139,6 +2151,11 @@ public Long zRank(String key, String value) {
21392151
return zRank(serialize(key), serialize(value));
21402152
}
21412153

2154+
@Override
2155+
public RankAndScore zRankWithScore(String key, String value) {
2156+
return zRankWithScore(serialize(key), serialize(value));
2157+
}
2158+
21422159
@Override
21432160
public Long zRem(String key, String... values) {
21442161
return zRem(serialize(key), serializeMulti(values));
@@ -2195,6 +2212,11 @@ public Long zRevRank(String key, String value) {
21952212
return zRevRank(serialize(key), serialize(value));
21962213
}
21972214

2215+
@Override
2216+
public RankAndScore zRevRankWithScore(String key, String value) {
2217+
return zRevRankWithScore(serialize(key), serialize(value));
2218+
}
2219+
21982220
@Override
21992221
public Double zScore(String key, String value) {
22002222
return zScore(serialize(key), serialize(value));

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.data.redis.connection.stream.StreamOffset;
4444
import org.springframework.data.redis.connection.stream.StreamReadOptions;
4545
import org.springframework.data.redis.connection.zset.Aggregate;
46+
import org.springframework.data.redis.connection.zset.RankAndScore;
4647
import org.springframework.data.redis.connection.zset.Tuple;
4748
import org.springframework.data.redis.connection.zset.Weights;
4849
import org.springframework.data.redis.core.Cursor;
@@ -67,6 +68,7 @@
6768
* @author Dennis Neufeld
6869
* @author Shyngys Sapraliyev
6970
* @author Tihomir Mateev
71+
* @author Seongil Kim
7072
* @since 2.0
7173
*/
7274
@Deprecated
@@ -1242,6 +1244,13 @@ default Long zRank(byte[] key, byte[] value) {
12421244
return zSetCommands().zRank(key, value);
12431245
}
12441246

1247+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1248+
@Override
1249+
@Deprecated
1250+
default RankAndScore zRankWithScore(byte[] key, byte[] value) {
1251+
return zSetCommands().zRankWithScore(key, value);
1252+
}
1253+
12451254
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
12461255
@Override
12471256
@Deprecated
@@ -1291,6 +1300,13 @@ default Long zRevRank(byte[] key, byte[] value) {
12911300
return zSetCommands().zRevRank(key, value);
12921301
}
12931302

1303+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1304+
@Override
1305+
@Deprecated
1306+
default RankAndScore zRevRankWithScore(byte[] key, byte[] value) {
1307+
return zSetCommands().zRevRankWithScore(key, value);
1308+
}
1309+
12941310
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
12951311
@Override
12961312
@Deprecated

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

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.springframework.data.redis.connection.ReactiveRedisConnection.*;
1919

20+
import org.springframework.data.redis.connection.zset.RankAndScore;
2021
import reactor.core.publisher.Flux;
2122
import reactor.core.publisher.Mono;
2223

@@ -51,6 +52,7 @@
5152
* @author Christoph Strobl
5253
* @author Mark Paluch
5354
* @author Andrey Shlykov
55+
* @author Seongil Kim
5456
* @since 2.0
5557
*/
5658
public interface ReactiveZSetCommands {
@@ -737,7 +739,24 @@ default Mono<Long> zRank(ByteBuffer key, ByteBuffer value) {
737739
}
738740

739741
/**
740-
* Determine the index of element with {@literal value} in a sorted set when scored high to low.
742+
* Determine the index and score of element with {@literal value} in a sorted set.
743+
*
744+
* @param key must not be {@literal null}.
745+
* @param value must not be {@literal null}.
746+
* @return
747+
* @see <a href="https://redis.io/commands/zrank">Redis Documentation: ZRANK</a>
748+
*/
749+
default Mono<RankAndScore> zRankWithScore(ByteBuffer key, ByteBuffer value) {
750+
751+
Assert.notNull(key, "Key must not be null");
752+
Assert.notNull(value, "Value must not be null");
753+
754+
return zRankWithScore(Mono.just(ZRankCommand.indexOf(value).storedWithin(key))).next()
755+
.map(CommandResponse::getOutput);
756+
}
757+
758+
/**
759+
* Determine the index and score of element with {@literal value} in a sorted set when scored high to low.
741760
*
742761
* @param key must not be {@literal null}.
743762
* @param value must not be {@literal null}.
@@ -753,6 +772,23 @@ default Mono<Long> zRevRank(ByteBuffer key, ByteBuffer value) {
753772
.map(NumericResponse::getOutput);
754773
}
755774

775+
/**
776+
* Determine the index and score of element with {@literal value} in a sorted set when scored high to low.
777+
*
778+
* @param key must not be {@literal null}.
779+
* @param value must not be {@literal null}.
780+
* @return
781+
* @see <a href="https://redis.io/commands/zrevrank">Redis Documentation: ZREVRANK</a>
782+
*/
783+
default Mono<RankAndScore> zRevRankWithScore(ByteBuffer key, ByteBuffer value) {
784+
785+
Assert.notNull(key, "Key must not be null");
786+
Assert.notNull(value, "Value must not be null");
787+
788+
return zRankWithScore(Mono.just(ZRankCommand.reverseIndexOf(value).storedWithin(key))).next()
789+
.map(CommandResponse::getOutput);
790+
}
791+
756792
/**
757793
* Determine the index of element with {@literal value} in a sorted set when scored by
758794
* {@link ZRankCommand#getDirection()}.
@@ -764,6 +800,17 @@ default Mono<Long> zRevRank(ByteBuffer key, ByteBuffer value) {
764800
*/
765801
Flux<NumericResponse<ZRankCommand, Long>> zRank(Publisher<ZRankCommand> commands);
766802

803+
/**
804+
* Determine the index and score of element with {@literal value} in a sorted set when scored by
805+
* {@link ZRankCommand#getDirection()}.
806+
*
807+
* @param commands must not be {@literal null}.
808+
* @return
809+
* @see <a href="https://redis.io/commands/zrank">Redis Documentation: ZRANK</a>
810+
* @see <a href="https://redis.io/commands/zrevrank">Redis Documentation: ZREVRANK</a>
811+
*/
812+
Flux<CommandResponse<ZRankCommand, RankAndScore>> zRankWithScore(Publisher<ZRankCommand> commands);
813+
767814
/**
768815
* {@code ZRANGE}/{@literal ZREVRANGE} command parameters.
769816
*

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.jspecify.annotations.NullUnmarked;
2626
import org.jspecify.annotations.Nullable;
2727
import org.springframework.data.redis.connection.zset.Aggregate;
28+
import org.springframework.data.redis.connection.zset.RankAndScore;
2829
import org.springframework.data.redis.connection.zset.Tuple;
2930
import org.springframework.data.redis.connection.zset.Weights;
3031
import org.springframework.data.redis.core.Cursor;
@@ -42,6 +43,7 @@
4243
* @author Mark Paluch
4344
* @author Andrey Shlykov
4445
* @author Shyngys Sapraliyev
46+
* @author Seongil Kim
4547
* @see RedisCommands
4648
*/
4749
@NullUnmarked
@@ -501,6 +503,17 @@ default Long zAdd(byte @NonNull [] key, @NonNull Set<@NonNull Tuple> tuples) {
501503
*/
502504
Long zRank(byte @NonNull [] key, byte @NonNull [] value);
503505

506+
/**
507+
* Determine the index and score of element with {@code value} in a sorted set.
508+
*
509+
* @param key must not be {@literal null}.
510+
* @param value the value. Must not be {@literal null}.
511+
* @return {@literal null} when used in pipeline / transaction.
512+
* @see <a href="https://redis.io/commands/zrank">Redis Documentation: ZRANK</a>
513+
*/
514+
@Nullable
515+
RankAndScore zRankWithScore(byte[] key, byte[] value);
516+
504517
/**
505518
* Determine the index of element with {@code value} in a sorted set when scored high to low.
506519
*
@@ -511,6 +524,17 @@ default Long zAdd(byte @NonNull [] key, @NonNull Set<@NonNull Tuple> tuples) {
511524
*/
512525
Long zRevRank(byte @NonNull [] key, byte @NonNull [] value);
513526

527+
/**
528+
* Determine the index and score of element with {@code value} in a sorted set when scored high to low.
529+
*
530+
* @param key must not be {@literal null}.
531+
* @param value the value.
532+
* @return {@literal null} when used in pipeline / transaction.
533+
* @see <a href="https://redis.io/commands/zrevrank">Redis Documentation: ZREVRANK</a>
534+
*/
535+
@Nullable
536+
RankAndScore zRevRankWithScore(byte[] key, byte[] value);
537+
514538
/**
515539
* Get elements between {@code start} and {@code end} from sorted set.
516540
*

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.springframework.data.redis.connection.stream.StreamRecords;
4646
import org.springframework.data.redis.connection.stream.StringRecord;
4747
import org.springframework.data.redis.connection.zset.Aggregate;
48+
import org.springframework.data.redis.connection.zset.RankAndScore;
4849
import org.springframework.data.redis.connection.zset.Tuple;
4950
import org.springframework.data.redis.connection.zset.Weights;
5051
import org.springframework.data.redis.core.Cursor;
@@ -73,6 +74,7 @@
7374
* @author Andrey Shlykov
7475
* @author ihaohong
7576
* @author Shyngys Sapraliyev
77+
* @author Seongil Kim
7678
* @see RedisCallback
7779
* @see RedisSerializer
7880
* @see StringRedisTemplate
@@ -1391,6 +1393,17 @@ String bLMove(@NonNull String sourceKey, @NonNull String destinationKey, @NonNul
13911393
*/
13921394
Long zRank(@NonNull String key, String value);
13931395

1396+
/**
1397+
* Determine the index and score of element with {@code value} in a sorted set.
1398+
*
1399+
* @param key must not be {@literal null}.
1400+
* @param value the value.
1401+
* @return
1402+
* @see <a href="https://redis.io/commands/zrank">Redis Documentation: ZRANK</a>
1403+
* @see RedisZSetCommands#zRankWithScore(byte[], byte[])
1404+
*/
1405+
RankAndScore zRankWithScore(String key, String value);
1406+
13941407
/**
13951408
* Determine the index of element with {@code value} in a sorted set when scored high to low.
13961409
*
@@ -1402,6 +1415,17 @@ String bLMove(@NonNull String sourceKey, @NonNull String destinationKey, @NonNul
14021415
*/
14031416
Long zRevRank(@NonNull String key, String value);
14041417

1418+
/**
1419+
* Determine the index and score of element with {@code value} in a sorted set when scored high to low.
1420+
*
1421+
* @param key must not be {@literal null}.
1422+
* @param value the value.
1423+
* @return
1424+
* @see <a href="https://redis.io/commands/zrevrank">Redis Documentation: ZREVRANK</a>
1425+
* @see RedisZSetCommands#zRevRankWithScore(byte[], byte[])
1426+
*/
1427+
RankAndScore zRevRankWithScore(String key, String value);
1428+
14051429
/**
14061430
* Get elements between {@code start} and {@code end} from sorted set.
14071431
*

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.redis.connection.jedis;
1717

18+
import org.springframework.data.redis.connection.zset.RankAndScore;
1819
import redis.clients.jedis.Protocol;
1920
import redis.clients.jedis.params.ScanParams;
2021
import redis.clients.jedis.params.ZParams;
@@ -58,6 +59,7 @@
5859
* @author Jens Deppe
5960
* @author Shyngys Sapraliyev
6061
* @author John Blum
62+
* @author Seongil Kim
6163
* @since 2.0
6264
*/
6365
@NullUnmarked
@@ -192,6 +194,20 @@ public Long zRank(byte @NonNull [] key, byte @NonNull [] value) {
192194
}
193195
}
194196

197+
@Override
198+
public RankAndScore zRankWithScore(byte[] key, byte[] value) {
199+
200+
Assert.notNull(key, "Key must not be null");
201+
Assert.notNull(value, "Value must not be null");
202+
203+
try {
204+
KeyValue<Long, Double> rankWithScore = connection.getCluster().zrankWithScore(key, value);
205+
return new RankAndScore(rankWithScore.getKey(), rankWithScore.getValue());
206+
} catch (Exception ex) {
207+
throw convertJedisAccessException(ex);
208+
}
209+
}
210+
195211
@Override
196212
public Long zRevRank(byte @NonNull [] key, byte @NonNull [] value) {
197213

@@ -205,6 +221,20 @@ public Long zRevRank(byte @NonNull [] key, byte @NonNull [] value) {
205221
}
206222
}
207223

224+
@Override
225+
public RankAndScore zRevRankWithScore(byte[] key, byte[] value) {
226+
227+
Assert.notNull(key, "Key must not be null");
228+
Assert.notNull(value, "Value must not be null");
229+
230+
try {
231+
KeyValue<Long, Double> rankWithScore = connection.getCluster().zrevrankWithScore(key, value);
232+
return new RankAndScore(rankWithScore.getKey(), rankWithScore.getValue());
233+
} catch (Exception ex) {
234+
throw convertJedisAccessException(ex);
235+
}
236+
}
237+
208238
@Override
209239
public Set<byte @NonNull []> zRange(byte @NonNull [] key, long start, long end) {
210240

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.redis.connection.jedis;
1717

18+
import org.springframework.data.redis.connection.zset.RankAndScore;
1819
import redis.clients.jedis.GeoCoordinate;
1920
import redis.clients.jedis.HostAndPort;
2021
import redis.clients.jedis.Protocol;
@@ -30,6 +31,7 @@
3031
import redis.clients.jedis.params.SortingParams;
3132
import redis.clients.jedis.params.ZAddParams;
3233
import redis.clients.jedis.resps.GeoRadiusResponse;
34+
import redis.clients.jedis.util.KeyValue;
3335
import redis.clients.jedis.util.SafeEncoder;
3436

3537
import java.nio.ByteBuffer;
@@ -104,6 +106,7 @@
104106
* @author Guy Korland
105107
* @author dengliming
106108
* @author John Blum
109+
* @author Seongil Kim
107110
*/
108111
@SuppressWarnings("ConstantConditions")
109112
abstract class JedisConverters extends Converters {
@@ -152,6 +155,15 @@ static List<Tuple> toTupleList(List<redis.clients.jedis.resps.Tuple> source) {
152155
return tuplesToTuples().convert(source);
153156
}
154157

158+
static RankAndScore toRankAndScore(KeyValue<Long, Double> source) {
159+
160+
Assert.notNull(source, "KeyValue must not be null");
161+
Assert.notNull(source.getKey(), "Key must not be null");
162+
Assert.notNull(source.getValue(), "Value must not be null");
163+
164+
return new RankAndScore(source.getKey(), source.getValue());
165+
}
166+
155167
/**
156168
* Map a {@link Set} of {@link Tuple} by {@code value} to its {@code score}.
157169
*

0 commit comments

Comments
 (0)