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.
This commit is contained in:
committed by
Mark Paluch
parent
04707ecc27
commit
507a882e93
@@ -1581,6 +1581,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return convertAndReturn(delegate.zRemRange(key, start, end), Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByLex(byte[] key, Range range) {
|
||||
return convertAndReturn(delegate.zRemRangeByLex(key, range), Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], double, double)
|
||||
@@ -2829,6 +2838,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return zRemRange(serialize(key), start, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zRemRange(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByLex(String key, Range range) {
|
||||
return zRemRangeByLex(serialize(key), range);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zRemRangeByScore(java.lang.String, double, double)
|
||||
|
||||
@@ -1024,6 +1024,13 @@ public interface DefaultedRedisConnection extends RedisConnection {
|
||||
return zSetCommands().zRemRange(key, start, end);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default Long zRemRangeByLex(byte[] key, Range range) {
|
||||
return zSetCommands().zRemRangeByLex(key, range);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
|
||||
@@ -1444,6 +1444,82 @@ public interface ReactiveZSetCommands {
|
||||
*/
|
||||
Flux<NumericResponse<ZRemRangeByScoreCommand, Long>> zRemRangeByScore(Publisher<ZRemRangeByScoreCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code ZREMRANGEBYLEX} command parameters.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
class ZRemRangeByLexCommand extends KeyCommand {
|
||||
|
||||
private final Range<String> range;
|
||||
|
||||
private ZRemRangeByLexCommand(@Nullable ByteBuffer key, Range<String> range) {
|
||||
|
||||
super(key);
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ZRemRangeByLexCommand} given a {@link Range}.
|
||||
*
|
||||
* @param range must not be {@literal null}.
|
||||
* @return a new {@link ZRemRangeByScoreCommand} for {@link Range}.
|
||||
*/
|
||||
public static ZRemRangeByLexCommand lexWithin(Range<String> range) {
|
||||
return new ZRemRangeByLexCommand(null, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @return a new {@link ZRemRangeByLexCommand} with {@literal key} applied.
|
||||
*/
|
||||
public ZRemRangeByLexCommand from(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return new ZRemRangeByLexCommand(key, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Range<String> getRange() {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove elements in {@link Range} from sorted set with {@literal key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param range must not be {@literal null}.
|
||||
* @return a {@link Mono} emitting the number of removed elements.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
default Mono<Long> zRemRangeByLex(ByteBuffer key, Range<String> range) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(range, "Range must not be null!");
|
||||
|
||||
return zRemRangeByLex(Mono.just(ZRemRangeByLexCommand.lexWithin(range).from(key))).next()
|
||||
.map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove elements in {@link Range} from sorted set with {@link ZRemRangeByLexCommand#getKey()}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
Flux<NumericResponse<ZRemRangeByLexCommand, Long>> zRemRangeByLex(Publisher<ZRemRangeByLexCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code ZUNIONSTORE} command parameters.
|
||||
*
|
||||
|
||||
@@ -814,6 +814,17 @@ public interface RedisZSetCommands {
|
||||
@Nullable
|
||||
Long zRemRange(byte[] key, long start, long end);
|
||||
|
||||
/**
|
||||
* Remove all elements between the lexicographical {@link Range}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param range must not be {@literal null}.
|
||||
* @return the number of elements removed, or {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
Long zRemRangeByLex(byte[] key, Range range);
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
|
||||
*
|
||||
|
||||
@@ -1376,6 +1376,18 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
*/
|
||||
Long zRemRange(String key, long start, long end);
|
||||
|
||||
|
||||
/**
|
||||
* Remove all elements between the lexicographical {@link Range}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param range must not be {@literal null}.
|
||||
* @return the number of elements removed, or {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
Long zRemRangeByLex(String key, Range range);
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
|
||||
*
|
||||
|
||||
@@ -348,6 +348,26 @@ class JedisClusterZSetCommands implements RedisZSetCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByLex(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
|
||||
|
||||
try {
|
||||
return connection.getCluster().zremrangeByLex(key, min, max);
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRevRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
|
||||
|
||||
@@ -336,6 +336,22 @@ class JedisZSetCommands implements RedisZSetCommands {
|
||||
end);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByLex(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
|
||||
|
||||
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.MINUS_BYTES);
|
||||
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.PLUS_BYTES);
|
||||
|
||||
return connection.invoke().just(BinaryJedis::zremrangeByLex, MultiKeyPipelineBase::zremrangeByLex, key, min, max);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
|
||||
@@ -418,6 +418,24 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zRemRangeByLex(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZRemRangeByLexCommand, Long>> zRemRangeByLex(Publisher<ZRemRangeByLexCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Key must not be null!");
|
||||
Assert.notNull(command.getRange(), "Range must not be null!");
|
||||
|
||||
Mono<Long> result = cmd.zremrangebylex(command.getKey(), RangeConverter.toRange(command.getRange()));
|
||||
|
||||
return result.map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zUnionStore(org.reactivestreams.Publisher)
|
||||
|
||||
@@ -312,6 +312,20 @@ class LettuceZSetCommands implements RedisZSetCommands {
|
||||
return connection.invoke().just(RedisSortedSetAsyncCommands::zremrangebyrank, key, start, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long zRemRangeByLex(byte[] key, Range range) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(range, "Range must not be null for ZREMRANGEBYLEX!");
|
||||
|
||||
return connection.invoke().just(RedisSortedSetAsyncCommands::zremrangebylex, key,
|
||||
LettuceConverters.<byte[]> toRange(range, true));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRangeByScore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
|
||||
@@ -252,6 +252,17 @@ public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
Long removeRange(long start, long end);
|
||||
|
||||
/**
|
||||
* Remove elements in {@link Range} from sorted set with the bound key.
|
||||
*
|
||||
* @param range must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long removeRangeByLex(Range range);
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code min} and {@code max} from sorted set with the bound key.
|
||||
*
|
||||
|
||||
@@ -249,6 +249,15 @@ class DefaultBoundZSetOperations<K, V> extends DefaultBoundKeyOperations<K> impl
|
||||
return ops.removeRange(getKey(), start, end);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#removeRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Long removeRangeByLex(Range range) {
|
||||
return ops.removeRangeByLex(getKey(), range);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#removeRangeByScore(double, double)
|
||||
|
||||
@@ -383,6 +383,19 @@ class DefaultReactiveZSetOperations<K, V> implements ReactiveZSetOperations<K, V
|
||||
return createMono(connection -> connection.zRemRangeByRank(rawKey(key), range));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#removeRangebyLex(java.lang.Object, org.springframework.data.domain.Range)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> removeRangeByLex(K key, Range<String> range) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(range, "Range must not be null!");
|
||||
|
||||
return createMono(connection -> connection.zRemRangeByLex(rawKey(key), range));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#removeRangeByScore(java.lang.Object, org.springframework.data.domain.Range)
|
||||
|
||||
@@ -353,6 +353,17 @@ class DefaultZSetOperations<K, V> extends AbstractOperations<K, V> implements ZS
|
||||
return execute(connection -> connection.zRemRange(rawKey, start, end), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ZSetOperations#removeRangeByLex(java.lang.Object, Range)
|
||||
*/
|
||||
@Override
|
||||
public Long removeRangeByLex(K key, Range range) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
return execute(connection -> connection.zRemRangeByLex(rawKey, range), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ZSetOperations#removeRangeByScore(java.lang.Object, double, double)
|
||||
|
||||
@@ -310,6 +310,17 @@ public interface ReactiveZSetOperations<K, V> {
|
||||
*/
|
||||
Mono<Long> removeRange(K key, Range<Long> range);
|
||||
|
||||
/**
|
||||
* Remove elements in range from sorted set with {@code key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param range must not be {@literal null}.
|
||||
* @return a {@link Mono} emitting the number or removed elements.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebyrank">Redis Documentation: ZREMRANGEBYRANK</a>
|
||||
*/
|
||||
Mono<Long> removeRangeByLex(K key, Range<String> range);
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
|
||||
*
|
||||
|
||||
@@ -344,6 +344,18 @@ public interface ZSetOperations<K, V> {
|
||||
@Nullable
|
||||
Long removeRange(K key, long start, long end);
|
||||
|
||||
/**
|
||||
* Remove elements in {@link Range} from sorted set with {@literal key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param range must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zremrangebylex">Redis Documentation: ZREMRANGEBYLEX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long removeRangeByLex(K key, Range range);
|
||||
|
||||
/**
|
||||
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
|
||||
*
|
||||
|
||||
@@ -226,6 +226,16 @@ public class DefaultRedisZSet<E> extends AbstractRedisCollection<E> implements R
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.support.collections.RedisZSet#removeRangeByLex(org.springframework.data.redis.connection.RedisZSetCommands.Range)
|
||||
*/
|
||||
@Override
|
||||
public Set<E> removeByLex(Range range) {
|
||||
boundZSetOps.removeRangeByLex(range);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.support.collections.RedisZSet#removeByScore(double, double)
|
||||
|
||||
@@ -118,6 +118,15 @@ public interface RedisZSet<E> extends RedisCollection<E>, Set<E> {
|
||||
|
||||
RedisZSet<E> remove(long start, long end);
|
||||
|
||||
/**
|
||||
* Remove all elements in range.
|
||||
*
|
||||
* @param range must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.5
|
||||
*/
|
||||
Set<E> removeByLex(Range range);
|
||||
|
||||
RedisZSet<E> removeByScore(double min, double max);
|
||||
|
||||
/**
|
||||
|
||||
@@ -186,6 +186,15 @@ suspend fun <K : Any, V : Any> ReactiveZSetOperations<K, V>.scoreAndAwait(key: K
|
||||
suspend fun <K : Any, V : Any> ReactiveZSetOperations<K, V>.removeRangeAndAwait(key: K, range: Range<Long>): Long =
|
||||
removeRange(key, range).awaitSingle()
|
||||
|
||||
/**
|
||||
* Coroutines variant of [ReactiveZSetOperations.removeRangeByLex].
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.5
|
||||
*/
|
||||
suspend fun <K : Any, V : Any> ReactiveZSetOperations<K, V>.removeRangeByLexAndAwait(key: K, range: Range<String>): Long =
|
||||
removeRangeByLex(key, range).awaitSingle()
|
||||
|
||||
/**
|
||||
* Coroutines variant of [ReactiveZSetOperations.removeRangeByScore].
|
||||
*
|
||||
|
||||
@@ -1909,6 +1909,25 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, 2L, new LinkedHashSet<String>(0) }));
|
||||
}
|
||||
|
||||
@Test // GH-1816
|
||||
void testZRemRangeByLex() {
|
||||
|
||||
actual.add(connection.zAdd("myset", 0, "aaaa"));
|
||||
actual.add(connection.zAdd("myset", 0, "b"));
|
||||
actual.add(connection.zAdd("myset", 0, "c"));
|
||||
actual.add(connection.zAdd("myset", 0, "d"));
|
||||
actual.add(connection.zAdd("myset", 0, "e"));
|
||||
actual.add(connection.zAdd("myset", 0, "foo"));
|
||||
actual.add(connection.zAdd("myset", 0, "zap"));
|
||||
actual.add(connection.zAdd("myset", 0, "zip"));
|
||||
actual.add(connection.zAdd("myset", 0, "ALPHA"));
|
||||
actual.add(connection.zAdd("myset", 0, "alpha"));
|
||||
actual.add(connection.zRemRangeByLex("myset", Range.range().gte("alpha").lte("omega")));
|
||||
|
||||
actual.add(connection.zRange("myset", 0L, -1L));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, true,true, true, true,true, true, true,true, 6L, new LinkedHashSet<String>(Arrays.asList("ALPHA", "aaaa", "zap", "zip")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testZRemRangeByScore() {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
|
||||
@@ -948,6 +948,11 @@ class RedisConnectionUnitTests {
|
||||
return delegate.zRemRangeByScore(key, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zRemRangeByLex(byte[] key, Range range) {
|
||||
return delegate.zRemRangeByLex(key, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> zRangeByScore(byte[] key, Range range) {
|
||||
return delegate.zRangeByScore(key, range);
|
||||
|
||||
@@ -412,6 +412,26 @@ public class LettuceReactiveZSetCommandsIntegrationTests extends LettuceReactive
|
||||
assertThat(connection.zSetCommands().zRemRangeByRank(KEY_1_BBUFFER, ONE_TO_TWO).block()).isEqualTo(2L);
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-1816
|
||||
void zRemRangeByLexRemovesValuesCorrectly() {
|
||||
|
||||
nativeCommands.zadd(KEY_1, 0D, "aaaa");
|
||||
nativeCommands.zadd(KEY_1, 0D, "b");
|
||||
nativeCommands.zadd(KEY_1, 0D, "c");
|
||||
nativeCommands.zadd(KEY_1, 0D, "d");
|
||||
nativeCommands.zadd(KEY_1, 0D, "e");
|
||||
nativeCommands.zadd(KEY_1, 0D, "foo");
|
||||
nativeCommands.zadd(KEY_1, 0D, "zap");
|
||||
nativeCommands.zadd(KEY_1, 0D, "zip");
|
||||
nativeCommands.zadd(KEY_1, 0D, "ALPHA");
|
||||
nativeCommands.zadd(KEY_1, 0D, "alpha");
|
||||
|
||||
connection.zSetCommands().zRemRangeByLex(KEY_1_BBUFFER, Range.closed("alpha", "omega")) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(6L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-525
|
||||
void zRemRangeByScoreShouldRemoveValuesCorrectly() {
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ConnectionMockingRedisTemplate<K, V> extends RedisTemplate<K, V> {
|
||||
|
||||
private RedisConnection connectionMock;
|
||||
|
||||
private ConnectionMockingRedisTemplate() {
|
||||
|
||||
connectionMock = Mockito.mock(RedisConnection.class);
|
||||
|
||||
RedisConnectionFactory connectionFactory = Mockito.mock(RedisConnectionFactory.class);
|
||||
Mockito.when(connectionFactory.getConnection()).thenReturn(connectionMock);
|
||||
|
||||
setConnectionFactory(connectionFactory);
|
||||
}
|
||||
|
||||
static <K, V> ConnectionMockingRedisTemplate<K, V> template() {
|
||||
return builder().build();
|
||||
}
|
||||
|
||||
static MockTemplateBuilder builder() {
|
||||
return new MockTemplateBuilder();
|
||||
}
|
||||
|
||||
public RedisConnection verify() {
|
||||
return Mockito.verify(connectionMock);
|
||||
}
|
||||
|
||||
public byte[] serializeKey(K key) {
|
||||
return ((RedisSerializer<K>) getKeySerializer()).serialize(key);
|
||||
}
|
||||
|
||||
public RedisConnection never() {
|
||||
return Mockito.verify(connectionMock, Mockito.never());
|
||||
}
|
||||
|
||||
public RedisConnection doReturn(Object o) {
|
||||
return Mockito.doReturn(o).when(connectionMock);
|
||||
}
|
||||
|
||||
public static class MockTemplateBuilder {
|
||||
|
||||
private ConnectionMockingRedisTemplate template = new ConnectionMockingRedisTemplate();
|
||||
|
||||
public <K, V> ConnectionMockingRedisTemplate<K, V> build() {
|
||||
|
||||
template.afterPropertiesSet();
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class DefaultBoundZSetOperationsUnitTests {
|
||||
|
||||
DefaultBoundZSetOperations zSetOperations;
|
||||
ConnectionMockingRedisTemplate template;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
||||
template = ConnectionMockingRedisTemplate.template();
|
||||
zSetOperations = new DefaultBoundZSetOperations<>("key", template);
|
||||
}
|
||||
|
||||
@Test // GH-1816
|
||||
void delegatesRemoveRangeByLex() {
|
||||
|
||||
Range range = Range.range().gte("alpha").lte("omega");
|
||||
zSetOperations.removeRangeByLex(range);
|
||||
|
||||
template.verify().zRemRangeByLex(eq(template.serializeKey("key")), eq(range));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
class DefaultZSetOperationsUnitTests {
|
||||
|
||||
DefaultZSetOperations zSetOperations;
|
||||
ConnectionMockingRedisTemplate template;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
||||
template = ConnectionMockingRedisTemplate.template();
|
||||
zSetOperations = new DefaultZSetOperations<>(template);
|
||||
}
|
||||
|
||||
@Test // GH-1816
|
||||
void delegatesRemoveRangeByLex() {
|
||||
|
||||
Range range = Range.range().gte("alpha").lte("omega");
|
||||
zSetOperations.removeRangeByLex("key", range);
|
||||
|
||||
template.verify().zRemRangeByLex(eq(template.serializeKey("key")), eq(range));
|
||||
}
|
||||
}
|
||||
@@ -366,6 +366,21 @@ class ReactiveZSetOperationsExtensionsUnitTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test // GH-1816
|
||||
fun removeRangeByLex() {
|
||||
|
||||
val operations = mockk<ReactiveZSetOperations<String, String>>()
|
||||
every { operations.removeRangeByLex(any(), any()) } returns Mono.just(1)
|
||||
|
||||
runBlocking {
|
||||
assertThat(operations.removeRangeByLexAndAwait("foo", Range.unbounded())).isEqualTo(1)
|
||||
}
|
||||
|
||||
verify {
|
||||
operations.removeRangeByLex("foo", Range.unbounded())
|
||||
}
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-937
|
||||
fun removeRangeByScore() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user