Skip to content

Commit 507a882

Browse files
christophstroblmp911de
authored andcommitted
Add support for ZREMRANGEBYLEX.
We now support ZREMRANGEBYLEX for Synchronous, Reactive, ZSetOperations and RedisZSet. Also provide a Kotlin coroutines variant via the extension for ReactiveZSetOperations. Closes #1816. Original pull request: #1968.
1 parent 04707ec commit 507a882

25 files changed

+516
-0
lines changed

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

+18
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,15 @@ public Long zRemRange(byte[] key, long start, long end) {
15811581
return convertAndReturn(delegate.zRemRange(key, start, end), Converters.identityConverter());
15821582
}
15831583

1584+
/*
1585+
* (non-Javadoc)
1586+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
1587+
*/
1588+
@Override
1589+
public Long zRemRangeByLex(byte[] key, Range range) {
1590+
return convertAndReturn(delegate.zRemRangeByLex(key, range), Converters.identityConverter());
1591+
}
1592+
15841593
/*
15851594
* (non-Javadoc)
15861595
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], double, double)
@@ -2829,6 +2838,15 @@ public Long zRemRange(String key, long start, long end) {
28292838
return zRemRange(serialize(key), start, end);
28302839
}
28312840

2841+
/*
2842+
* (non-Javadoc)
2843+
* @see org.springframework.data.redis.connection.StringRedisConnection#zRemRange(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Range)
2844+
*/
2845+
@Override
2846+
public Long zRemRangeByLex(String key, Range range) {
2847+
return zRemRangeByLex(serialize(key), range);
2848+
}
2849+
28322850
/*
28332851
* (non-Javadoc)
28342852
* @see org.springframework.data.redis.connection.StringRedisConnection#zRemRangeByScore(java.lang.String, double, double)

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

+7
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,13 @@ default Long zRemRange(byte[] key, long start, long end) {
10241024
return zSetCommands().zRemRange(key, start, end);
10251025
}
10261026

1027+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1028+
@Override
1029+
@Deprecated
1030+
default Long zRemRangeByLex(byte[] key, Range range) {
1031+
return zSetCommands().zRemRangeByLex(key, range);
1032+
}
1033+
10271034
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
10281035
@Override
10291036
@Deprecated

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

+76
Original file line numberDiff line numberDiff line change
@@ -1444,6 +1444,82 @@ default Mono<Long> zRemRangeByScore(ByteBuffer key, Range<Double> range) {
14441444
*/
14451445
Flux<NumericResponse<ZRemRangeByScoreCommand, Long>> zRemRangeByScore(Publisher<ZRemRangeByScoreCommand> commands);
14461446

1447+
/**
1448+
* {@code ZREMRANGEBYLEX} command parameters.
1449+
*
1450+
* @author Christoph Strobl
1451+
* @since 2.5
1452+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
1453+
*/
1454+
class ZRemRangeByLexCommand extends KeyCommand {
1455+
1456+
private final Range<String> range;
1457+
1458+
private ZRemRangeByLexCommand(@Nullable ByteBuffer key, Range<String> range) {
1459+
1460+
super(key);
1461+
this.range = range;
1462+
}
1463+
1464+
/**
1465+
* Creates a new {@link ZRemRangeByLexCommand} given a {@link Range}.
1466+
*
1467+
* @param range must not be {@literal null}.
1468+
* @return a new {@link ZRemRangeByScoreCommand} for {@link Range}.
1469+
*/
1470+
public static ZRemRangeByLexCommand lexWithin(Range<String> range) {
1471+
return new ZRemRangeByLexCommand(null, range);
1472+
}
1473+
1474+
/**
1475+
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
1476+
*
1477+
* @param key must not be {@literal null}.
1478+
* @return a new {@link ZRemRangeByLexCommand} with {@literal key} applied.
1479+
*/
1480+
public ZRemRangeByLexCommand from(ByteBuffer key) {
1481+
1482+
Assert.notNull(key, "Key must not be null!");
1483+
1484+
return new ZRemRangeByLexCommand(key, range);
1485+
}
1486+
1487+
/**
1488+
* @return
1489+
*/
1490+
public Range<String> getRange() {
1491+
return range;
1492+
}
1493+
}
1494+
1495+
/**
1496+
* Remove elements in {@link Range} from sorted set with {@literal key}.
1497+
*
1498+
* @param key must not be {@literal null}.
1499+
* @param range must not be {@literal null}.
1500+
* @return a {@link Mono} emitting the number of removed elements.
1501+
* @since 2.5
1502+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
1503+
*/
1504+
default Mono<Long> zRemRangeByLex(ByteBuffer key, Range<String> range) {
1505+
1506+
Assert.notNull(key, "Key must not be null!");
1507+
Assert.notNull(range, "Range must not be null!");
1508+
1509+
return zRemRangeByLex(Mono.just(ZRemRangeByLexCommand.lexWithin(range).from(key))).next()
1510+
.map(NumericResponse::getOutput);
1511+
}
1512+
1513+
/**
1514+
* Remove elements in {@link Range} from sorted set with {@link ZRemRangeByLexCommand#getKey()}.
1515+
*
1516+
* @param commands must not be {@literal null}.
1517+
* @return
1518+
* @since 2.5
1519+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
1520+
*/
1521+
Flux<NumericResponse<ZRemRangeByLexCommand, Long>> zRemRangeByLex(Publisher<ZRemRangeByLexCommand> commands);
1522+
14471523
/**
14481524
* {@code ZUNIONSTORE} command parameters.
14491525
*

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

+11
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,17 @@ default Long zCount(byte[] key, double min, double max) {
814814
@Nullable
815815
Long zRemRange(byte[] key, long start, long end);
816816

817+
/**
818+
* Remove all elements between the lexicographical {@link Range}.
819+
*
820+
* @param key must not be {@literal null}.
821+
* @param range must not be {@literal null}.
822+
* @return the number of elements removed, or {@literal null} when used in pipeline / transaction.
823+
* @since 2.5
824+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
825+
*/
826+
Long zRemRangeByLex(byte[] key, Range range);
827+
817828
/**
818829
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
819830
*

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

+12
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,18 @@ default Long lPos(String key, String element) {
13761376
*/
13771377
Long zRemRange(String key, long start, long end);
13781378

1379+
1380+
/**
1381+
* Remove all elements between the lexicographical {@link Range}.
1382+
*
1383+
* @param key must not be {@literal null}.
1384+
* @param range must not be {@literal null}.
1385+
* @return the number of elements removed, or {@literal null} when used in pipeline / transaction.
1386+
* @since 2.5
1387+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
1388+
*/
1389+
Long zRemRangeByLex(String key, Range range);
1390+
13791391
/**
13801392
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
13811393
*

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

+20
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,26 @@ public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
348348
}
349349
}
350350

351+
/*
352+
* (non-Javadoc)
353+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
354+
*/
355+
@Override
356+
public Long zRemRangeByLex(byte[] key, Range range) {
357+
358+
Assert.notNull(key, "Key must not be null!");
359+
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
360+
361+
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
362+
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
363+
364+
try {
365+
return connection.getCluster().zremrangeByLex(key, min, max);
366+
} catch (Exception ex) {
367+
throw convertJedisAccessException(ex);
368+
}
369+
}
370+
351371
/*
352372
* (non-Javadoc)
353373
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)

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

+16
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,22 @@ public Long zRemRange(byte[] key, long start, long end) {
336336
end);
337337
}
338338

339+
/*
340+
* (non-Javadoc)
341+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
342+
*/
343+
@Override
344+
public Long zRemRangeByLex(byte[] key, Range range) {
345+
346+
Assert.notNull(key, "Key must not be null!");
347+
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
348+
349+
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
350+
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
351+
352+
return connection.invoke().just(BinaryJedis::zremrangeByLex, MultiKeyPipelineBase::zremrangeByLex, key, min, max);
353+
}
354+
339355
/*
340356
* (non-Javadoc)
341357
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)

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

+18
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,24 @@ public Flux<NumericResponse<ZRemRangeByScoreCommand, Long>> zRemRangeByScore(
418418
}));
419419
}
420420

421+
/*
422+
* (non-Javadoc)
423+
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zRemRangeByLex(org.reactivestreams.Publisher)
424+
*/
425+
@Override
426+
public Flux<NumericResponse<ZRemRangeByLexCommand, Long>> zRemRangeByLex(Publisher<ZRemRangeByLexCommand> commands) {
427+
428+
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
429+
430+
Assert.notNull(command.getKey(), "Key must not be null!");
431+
Assert.notNull(command.getRange(), "Range must not be null!");
432+
433+
Mono<Long> result = cmd.zremrangebylex(command.getKey(), RangeConverter.toRange(command.getRange()));
434+
435+
return result.map(value -> new NumericResponse<>(command, value));
436+
}));
437+
}
438+
421439
/*
422440
* (non-Javadoc)
423441
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zUnionStore(org.reactivestreams.Publisher)

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

+14
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,20 @@ public Long zRemRange(byte[] key, long start, long end) {
312312
return connection.invoke().just(RedisSortedSetAsyncCommands::zremrangebyrank, key, start, end);
313313
}
314314

315+
/*
316+
* (non-Javadoc)
317+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
318+
*/
319+
@Override
320+
public Long zRemRangeByLex(byte[] key, Range range) {
321+
322+
Assert.notNull(key, "Key must not be null!");
323+
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
324+
325+
return connection.invoke().just(RedisSortedSetAsyncCommands::zremrangebylex, key,
326+
LettuceConverters.<byte[]> toRange(range, true));
327+
}
328+
315329
/*
316330
* (non-Javadoc)
317331
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)

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

+11
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,17 @@ public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
252252
@Nullable
253253
Long removeRange(long start, long end);
254254

255+
/**
256+
* Remove elements in {@link Range} from sorted set with the bound key.
257+
*
258+
* @param range must not be {@literal null}.
259+
* @return {@literal null} when used in pipeline / transaction.
260+
* @since 2.5
261+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
262+
*/
263+
@Nullable
264+
Long removeRangeByLex(Range range);
265+
255266
/**
256267
* Remove elements with scores between {@code min} and {@code max} from sorted set with the bound key.
257268
*

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

+9
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ public Long removeRange(long start, long end) {
249249
return ops.removeRange(getKey(), start, end);
250250
}
251251

252+
/*
253+
* (non-Javadoc)
254+
* @see org.springframework.data.redis.core.BoundZSetOperations#removeRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range)
255+
*/
256+
@Override
257+
public Long removeRangeByLex(Range range) {
258+
return ops.removeRangeByLex(getKey(), range);
259+
}
260+
252261
/*
253262
* (non-Javadoc)
254263
* @see org.springframework.data.redis.core.BoundZSetOperations#removeRangeByScore(double, double)

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

+13
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,19 @@ public Mono<Long> removeRange(K key, Range<Long> range) {
383383
return createMono(connection -> connection.zRemRangeByRank(rawKey(key), range));
384384
}
385385

386+
/*
387+
* (non-Javadoc)
388+
* @see org.springframework.data.redis.core.ReactiveZSetOperations#removeRangebyLex(java.lang.Object, org.springframework.data.domain.Range)
389+
*/
390+
@Override
391+
public Mono<Long> removeRangeByLex(K key, Range<String> range) {
392+
393+
Assert.notNull(key, "Key must not be null!");
394+
Assert.notNull(range, "Range must not be null!");
395+
396+
return createMono(connection -> connection.zRemRangeByLex(rawKey(key), range));
397+
}
398+
386399
/*
387400
* (non-Javadoc)
388401
* @see org.springframework.data.redis.core.ReactiveZSetOperations#removeRangeByScore(java.lang.Object, org.springframework.data.domain.Range)

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

+11
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,17 @@ public Long removeRange(K key, long start, long end) {
353353
return execute(connection -> connection.zRemRange(rawKey, start, end), true);
354354
}
355355

356+
/*
357+
* (non-Javadoc)
358+
* @see org.springframework.data.redis.core.ZSetOperations#removeRangeByLex(java.lang.Object, Range)
359+
*/
360+
@Override
361+
public Long removeRangeByLex(K key, Range range) {
362+
363+
byte[] rawKey = rawKey(key);
364+
return execute(connection -> connection.zRemRangeByLex(rawKey, range), true);
365+
}
366+
356367
/*
357368
* (non-Javadoc)
358369
* @see org.springframework.data.redis.core.ZSetOperations#removeRangeByScore(java.lang.Object, double, double)

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

+11
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,17 @@ default Flux<TypedTuple<V>> scan(K key) {
310310
*/
311311
Mono<Long> removeRange(K key, Range<Long> range);
312312

313+
/**
314+
* Remove elements in range from sorted set with {@code key}.
315+
*
316+
* @param key must not be {@literal null}.
317+
* @param range must not be {@literal null}.
318+
* @return a {@link Mono} emitting the number or removed elements.
319+
* @since 2.5
320+
* @see <a href="https://redis.io/commands/zremrangebyrank">Redis Documentation: ZREMRANGEBYRANK</a>
321+
*/
322+
Mono<Long> removeRangeByLex(K key, Range<String> range);
323+
313324
/**
314325
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
315326
*

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

+12
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,18 @@ interface TypedTuple<V> extends Comparable<TypedTuple<V>> {
344344
@Nullable
345345
Long removeRange(K key, long start, long end);
346346

347+
/**
348+
* Remove elements in {@link Range} from sorted set with {@literal key}.
349+
*
350+
* @param key must not be {@literal null}.
351+
* @param range must not be {@literal null}.
352+
* @return {@literal null} when used in pipeline / transaction.
353+
* @since 2.5
354+
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
355+
*/
356+
@Nullable
357+
Long removeRangeByLex(K key, Range range);
358+
347359
/**
348360
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
349361
*

src/main/java/org/springframework/data/redis/support/collections/DefaultRedisZSet.java

+10
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@ public RedisZSet<E> remove(long start, long end) {
226226
return this;
227227
}
228228

229+
/*
230+
* (non-Javadoc)
231+
* @see org.springframework.data.redis.support.collections.RedisZSet#removeRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range)
232+
*/
233+
@Override
234+
public Set<E> removeByLex(Range range) {
235+
boundZSetOps.removeRangeByLex(range);
236+
return this;
237+
}
238+
229239
/*
230240
* (non-Javadoc)
231241
* @see org.springframework.data.redis.support.collections.RedisZSet#removeByScore(double, double)

0 commit comments

Comments
 (0)