Add reactive support for ZDIFF, ZDIFFSTORE, ZINTER, and ZUNION commands.
See: #2041 & #2042 Original Pull Request: #2097
This commit is contained in:
committed by
Christoph Strobl
parent
8dc6f014ee
commit
38d3576052
File diff suppressed because it is too large
Load Diff
@@ -1174,34 +1174,6 @@ public interface RedisZSetCommands {
|
||||
@Nullable
|
||||
Set<byte[]> zInter(byte[]... sets);
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @param sets must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Set<byte[]> zInter(Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
return zInter(aggregate, Weights.of(weights), sets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @param sets must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
@Nullable
|
||||
Set<byte[]> zInter(Aggregate aggregate, Weights weights, byte[]... sets);
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
@@ -1293,34 +1265,6 @@ public interface RedisZSetCommands {
|
||||
@Nullable
|
||||
Set<byte[]> zUnion(byte[]... sets);
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @param sets must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Set<byte[]> zUnion(Aggregate aggregate, int[] weights, byte[]... sets) {
|
||||
return zUnion(aggregate, Weights.of(weights), sets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @param sets must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
@Nullable
|
||||
Set<byte[]> zUnion(Aggregate aggregate, Weights weights, byte[]... sets);
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
|
||||
@@ -41,11 +41,13 @@ class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetCommands imp
|
||||
super(connection);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceReactiveZSetCommands#zUnionStore(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZUnionStoreCommand, Long>> zUnionStore(Publisher<ZUnionStoreCommand> commands) {
|
||||
public Flux<NumericResponse<ZAggregateStoreCommand, Long>> zUnionStore(
|
||||
Publisher<? extends ZAggregateStoreCommand> commands) {
|
||||
|
||||
return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
@@ -60,11 +62,13 @@ class LettuceReactiveClusterZSetCommands extends LettuceReactiveZSetCommands imp
|
||||
}));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.lettuce.LettuceReactiveZSetCommands#zInterStore(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZInterStoreCommand, Long>> zInterStore(Publisher<ZInterStoreCommand> commands) {
|
||||
public Flux<NumericResponse<ZAggregateStoreCommand, Long>> zInterStore(
|
||||
Publisher<? extends ZAggregateStoreCommand> commands) {
|
||||
return getConnection().execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty.");
|
||||
|
||||
@@ -200,22 +200,18 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
if (ObjectUtils.nullSafeEquals(command.getDirection(), Direction.ASC)) {
|
||||
if (command.isWithScores()) {
|
||||
|
||||
result = cmd.zrangeWithScores(command.getKey(), start, stop)
|
||||
.map(this::toTuple);
|
||||
result = cmd.zrangeWithScores(command.getKey(), start, stop).map(this::toTuple);
|
||||
} else {
|
||||
|
||||
result = cmd.zrange(command.getKey(), start, stop)
|
||||
.map(value -> toTuple(value, Double.NaN));
|
||||
result = cmd.zrange(command.getKey(), start, stop).map(value -> toTuple(value, Double.NaN));
|
||||
}
|
||||
} else {
|
||||
if (command.isWithScores()) {
|
||||
|
||||
result = cmd.zrevrangeWithScores(command.getKey(), start, stop)
|
||||
.map(this::toTuple);
|
||||
result = cmd.zrevrangeWithScores(command.getKey(), start, stop).map(this::toTuple);
|
||||
} else {
|
||||
|
||||
result = cmd.zrevrange(command.getKey(), start, stop)
|
||||
.map(value -> toTuple(value, Double.NaN));
|
||||
result = cmd.zrevrange(command.getKey(), start, stop).map(value -> toTuple(value, Double.NaN));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +243,7 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
if (command.isWithScores()) {
|
||||
|
||||
if (!isLimited) {
|
||||
result = cmd.zrangebyscoreWithScores(command.getKey(), range)
|
||||
.map(this::toTuple);
|
||||
result = cmd.zrangebyscoreWithScores(command.getKey(), range).map(this::toTuple);
|
||||
} else {
|
||||
result = cmd
|
||||
.zrangebyscoreWithScores(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get()))
|
||||
@@ -257,8 +252,7 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
} else {
|
||||
|
||||
if (!isLimited) {
|
||||
result = cmd.zrangebyscore(command.getKey(), range)
|
||||
.map(value -> toTuple(value, Double.NaN));
|
||||
result = cmd.zrangebyscore(command.getKey(), range).map(value -> toTuple(value, Double.NaN));
|
||||
} else {
|
||||
|
||||
result = cmd.zrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get()))
|
||||
@@ -272,20 +266,16 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
if (command.isWithScores()) {
|
||||
|
||||
if (!isLimited) {
|
||||
result = cmd.zrevrangebyscoreWithScores(command.getKey(), range)
|
||||
.map(this::toTuple);
|
||||
result = cmd.zrevrangebyscoreWithScores(command.getKey(), range).map(this::toTuple);
|
||||
} else {
|
||||
|
||||
result = cmd
|
||||
.zrevrangebyscoreWithScores(command.getKey(), range,
|
||||
LettuceConverters.toLimit(command.getLimit().get()))
|
||||
.map(this::toTuple);
|
||||
result = cmd.zrevrangebyscoreWithScores(command.getKey(), range,
|
||||
LettuceConverters.toLimit(command.getLimit().get())).map(this::toTuple);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!isLimited) {
|
||||
result = cmd.zrevrangebyscore(command.getKey(), range)
|
||||
.map(value -> toTuple(value, Double.NaN));
|
||||
result = cmd.zrevrangebyscore(command.getKey(), range).map(value -> toTuple(value, Double.NaN));
|
||||
} else {
|
||||
|
||||
result = cmd.zrevrangebyscore(command.getKey(), range, LettuceConverters.toLimit(command.getLimit().get()))
|
||||
@@ -518,12 +508,186 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zDiff(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZDiffCommand, Flux<ByteBuffer>>> zDiff(Publisher<? extends ZDiffCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getKeys(), "Keys must not be null or empty!");
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getKeys().toArray(new ByteBuffer[0]);
|
||||
return new CommandResponse<>(command, cmd.zdiff(sourceKeys));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zDiffWithScores(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZDiffCommand, Flux<Tuple>>> zDiffWithScores(Publisher<? extends ZDiffCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getKeys(), "Keys must not be null or empty!");
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getKeys().toArray(new ByteBuffer[0]);
|
||||
return new CommandResponse<>(command, cmd.zdiffWithScores(sourceKeys).map(this::toTuple));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zDiffStore(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZDiffStoreCommand, Long>> zDiffStore(Publisher<ZDiffStoreCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Destination key must not be null!");
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().toArray(new ByteBuffer[0]);
|
||||
return cmd.zdiffstore(command.getKey(), sourceKeys).map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zInter(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZAggregateCommand, Flux<ByteBuffer>>> zInter(
|
||||
Publisher<? extends ZAggregateCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().toArray(new ByteBuffer[0]);
|
||||
Flux<ByteBuffer> result = args != null ? cmd.zinter(args, sourceKeys) : cmd.zinter(sourceKeys);
|
||||
return new CommandResponse<>(command, result);
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zInterWithScores(Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZAggregateCommand, Flux<Tuple>>> zInterWithScores(
|
||||
Publisher<? extends ZAggregateCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().toArray(new ByteBuffer[0]);
|
||||
Flux<ScoredValue<ByteBuffer>> result = args != null ? cmd.zinterWithScores(args, sourceKeys)
|
||||
: cmd.zinterWithScores(sourceKeys);
|
||||
return new CommandResponse<>(command, result.map(this::toTuple));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zInterStore(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZAggregateStoreCommand, Long>> zInterStore(
|
||||
Publisher<? extends ZAggregateStoreCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Destination key must not be null!");
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().toArray(new ByteBuffer[0]);
|
||||
Mono<Long> result = args != null ? cmd.zinterstore(command.getKey(), args, sourceKeys)
|
||||
: cmd.zinterstore(command.getKey(), sourceKeys);
|
||||
return result.map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zUnion(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZAggregateCommand, Flux<ByteBuffer>>> zUnion(
|
||||
Publisher<? extends ZAggregateCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().stream().toArray(ByteBuffer[]::new);
|
||||
Flux<ByteBuffer> result = args != null ? cmd.zunion(args, sourceKeys) : cmd.zunion(sourceKeys);
|
||||
return new CommandResponse<>(command, result);
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zUnion(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<CommandResponse<ZAggregateCommand, Flux<Tuple>>> zUnionWithScores(
|
||||
Publisher<? extends ZAggregateCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).map(command -> {
|
||||
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().stream().toArray(ByteBuffer[]::new);
|
||||
Flux<ScoredValue<ByteBuffer>> result = args != null ? cmd.zunionWithScores(args, sourceKeys)
|
||||
: cmd.zunionWithScores(sourceKeys);
|
||||
return new CommandResponse<>(command, result.map(this::toTuple));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zUnionStore(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZUnionStoreCommand, Long>> zUnionStore(Publisher<ZUnionStoreCommand> commands) {
|
||||
public Flux<NumericResponse<ZAggregateStoreCommand, Long>> zUnionStore(
|
||||
Publisher<? extends ZAggregateStoreCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
@@ -543,31 +707,6 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zInterStore(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<ZInterStoreCommand, Long>> zInterStore(Publisher<ZInterStoreCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
Assert.notNull(command.getKey(), "Destination key must not be null!");
|
||||
Assert.notEmpty(command.getSourceKeys(), "Source keys must not be null or empty!");
|
||||
|
||||
ZStoreArgs args = null;
|
||||
if (command.getAggregateFunction().isPresent() || !command.getWeights().isEmpty()) {
|
||||
args = zStoreArgs(command.getAggregateFunction().isPresent() ? command.getAggregateFunction().get() : null,
|
||||
command.getWeights());
|
||||
}
|
||||
|
||||
ByteBuffer[] sourceKeys = command.getSourceKeys().stream().toArray(ByteBuffer[]::new);
|
||||
Mono<Long> result = args != null ? cmd.zinterstore(command.getKey(), args, sourceKeys)
|
||||
: cmd.zinterstore(command.getKey(), sourceKeys);
|
||||
return result.map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zRangeByLex(org.reactivestreams.Publisher)
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.redis.connection.DefaultTuple;
|
||||
import org.springframework.data.redis.connection.ReactiveZSetCommands;
|
||||
@@ -501,6 +500,194 @@ class DefaultReactiveZSetOperations<K, V> implements ReactiveZSetOperations<K, V
|
||||
return createMono(connection -> connection.zRemRangeByScore(rawKey(key), range));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#difference(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<V> difference(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zDiff).map(this::readValue));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#differenceWithScores(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<TypedTuple<V>> differenceWithScores(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zDiffWithScores).map(this::readTypedTuple));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#differenceAndStore(K, Collection, K)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> differenceAndStore(K key, Collection<K> otherKeys, K destKey) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
|
||||
return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMap(serialized -> connection.zDiffStore(rawKey(destKey), serialized)));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersect(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<V> intersect(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zInter).map(this::readValue));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectWithScores(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<TypedTuple<V>> intersectWithScores(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zInterWithScores).map(this::readTypedTuple));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectWithScores(K, Collection, Aggregate, Weights)
|
||||
*/
|
||||
@Override
|
||||
public Flux<TypedTuple<V>> intersectWithScores(K key, Collection<K> otherKeys, Aggregate aggregate, Weights weights) {
|
||||
|
||||
// TODO: Inconsistent method signatures Aggregate/Weights vs Weights/Aggregate in Connection API
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(aggregate, "Aggregate must not be null!");
|
||||
Assert.notNull(weights, "Weights must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(sets -> connection.zInterWithScores(sets, weights, aggregate)).map(this::readTypedTuple));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectAndStore(java.lang.Object, java.util.Collection, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
|
||||
return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectAndStore(java.lang.Object, java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, org.springframework.data.redis.connection.RedisZSetCommands.Weights)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate, Weights weights) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
Assert.notNull(aggregate, "Aggregate must not be null!");
|
||||
Assert.notNull(weights, "Weights must not be null!");
|
||||
|
||||
return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized, weights, aggregate)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#union(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<V> union(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zUnion).map(this::readValue));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#unionWithScores(K, Collection)
|
||||
*/
|
||||
@Override
|
||||
public Flux<TypedTuple<V>> unionWithScores(K key, Collection<K> otherKeys) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(connection::zUnionWithScores).map(this::readTypedTuple));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#unionWithScores(K, Collection, Aggregate, Weights)
|
||||
*/
|
||||
@Override
|
||||
public Flux<TypedTuple<V>> unionWithScores(K key, Collection<K> otherKeys, Aggregate aggregate, Weights weights) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(aggregate, "Aggregate must not be null!");
|
||||
Assert.notNull(weights, "Weights must not be null!");
|
||||
|
||||
return createFlux(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMapMany(sets -> connection.zUnionWithScores(sets, weights, aggregate)).map(this::readTypedTuple));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#unionAndStore(java.lang.Object, java.lang.Object, java.lang.Object)
|
||||
@@ -551,56 +738,6 @@ class DefaultReactiveZSetOperations<K, V> implements ReactiveZSetOperations<K, V
|
||||
.flatMap(serialized -> connection.zUnionStore(rawKey(destKey), serialized, weights, aggregate)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectAndStore(java.lang.Object, java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> intersectAndStore(K key, K otherKey, K destKey) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKey, "Other key must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
|
||||
return intersectAndStore(key, Collections.singleton(otherKey), destKey);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectAndStore(java.lang.Object, java.util.Collection, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
|
||||
return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#intersectAndStore(java.lang.Object, java.util.Collection, java.lang.Object, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, org.springframework.data.redis.connection.RedisZSetCommands.Weights)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate, Weights weights) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(otherKeys, "Other keys must not be null!");
|
||||
Assert.notNull(destKey, "Destination key must not be null!");
|
||||
Assert.notNull(aggregate, "Aggregate must not be null!");
|
||||
Assert.notNull(weights, "Weights must not be null!");
|
||||
|
||||
return createMono(connection -> Flux.fromIterable(getKeys(key, otherKeys)) //
|
||||
.map(this::rawKey) //
|
||||
.collectList() //
|
||||
.flatMap(serialized -> connection.zInterStore(rawKey(destKey), serialized, weights, aggregate)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveZSetOperations#rangeByLex(java.lang.Object, org.springframework.data.domain.Range)
|
||||
|
||||
@@ -20,6 +20,7 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Range;
|
||||
@@ -412,6 +413,283 @@ public interface ReactiveZSetOperations<K, V> {
|
||||
*/
|
||||
Mono<Long> removeRangeByScore(K key, Range<Double> range);
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiff">Redis Documentation: ZDIFF</a>
|
||||
*/
|
||||
default Flux<V> difference(K key, K otherKey) {
|
||||
return difference(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiff">Redis Documentation: ZDIFF</a>
|
||||
*/
|
||||
Flux<V> difference(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiff">Redis Documentation: ZDIFF</a>
|
||||
*/
|
||||
default Flux<TypedTuple<V>> differenceWithScores(K key, K otherKey) {
|
||||
return differenceWithScores(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiff">Redis Documentation: ZDIFF</a>
|
||||
*/
|
||||
Flux<TypedTuple<V>> differenceWithScores(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiffstore">Redis Documentation: ZDIFFSTORE</a>
|
||||
*/
|
||||
default Mono<Long> differenceAndStore(K key, K otherKey, K destKey) {
|
||||
return differenceAndStore(key, Collections.singleton(otherKey), destKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff sorted {@code sets} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zdiffstore">Redis Documentation: ZDIFFSTORE</a>
|
||||
*/
|
||||
Mono<Long> differenceAndStore(K key, Collection<K> otherKeys, K destKey);
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
default Flux<V> intersect(K key, K otherKey) {
|
||||
return intersect(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
Flux<V> intersect(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
default Flux<TypedTuple<V>> intersectWithScores(K key, K otherKey) {
|
||||
return intersectWithScores(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
Flux<TypedTuple<V>> intersectWithScores(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} .
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
default Flux<TypedTuple<V>> intersectWithScores(K key, Collection<K> otherKeys, Aggregate aggregate) {
|
||||
return intersectWithScores(key, otherKeys, aggregate, Weights.fromSetCount(1 + otherKeys.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zinter">Redis Documentation: ZINTER</a>
|
||||
*/
|
||||
Flux<TypedTuple<V>> intersectWithScores(K key, Collection<K> otherKeys, Aggregate aggregate, Weights weights);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKey} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
default Mono<Long> intersectAndStore(K key, K otherKey, K destKey) {
|
||||
return intersectAndStore(key, Collections.singleton(otherKey), destKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
default Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate) {
|
||||
return intersectAndStore(key, otherKeys, destKey, aggregate, Weights.fromSetCount(1 + otherKeys.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate, Weights weights);
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
default Flux<V> union(K key, K otherKey) {
|
||||
return union(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
Flux<V> union(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
default Flux<TypedTuple<V>> unionWithScores(K key, K otherKey) {
|
||||
return unionWithScores(key, Collections.singleton(otherKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
Flux<TypedTuple<V>> unionWithScores(K key, Collection<K> otherKeys);
|
||||
|
||||
/**
|
||||
* Union sorted sets at {@code key} and {@code otherKeys} .
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
default Flux<TypedTuple<V>> unionWithScores(K key, Collection<K> otherKeys, Aggregate aggregate) {
|
||||
return unionWithScores(key, otherKeys, aggregate, Weights.fromSetCount(1 + otherKeys.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Union sorted {@code sets}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.6
|
||||
* @see <a href="https://redis.io/commands/zunion">Redis Documentation: ZUNION</a>
|
||||
*/
|
||||
Flux<TypedTuple<V>> unionWithScores(K key, Collection<K> otherKeys, Aggregate aggregate, Weights weights);
|
||||
|
||||
/**
|
||||
* Union sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
@@ -463,57 +741,6 @@ public interface ReactiveZSetOperations<K, V> {
|
||||
*/
|
||||
Mono<Long> unionAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate, Weights weights);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKey} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKey must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
Mono<Long> intersectAndStore(K key, K otherKey, K destKey);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @return
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey);
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
default Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate) {
|
||||
return intersectAndStore(key, otherKeys, destKey, aggregate, Weights.fromSetCount(1 + otherKeys.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect sorted sets at {@code key} and {@code otherKeys} and store result in destination {@code destKey}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param otherKeys must not be {@literal null}.
|
||||
* @param destKey must not be {@literal null}.
|
||||
* @param aggregate must not be {@literal null}.
|
||||
* @param weights must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
* @see <a href="https://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
|
||||
*/
|
||||
Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, Aggregate aggregate, Weights weights);
|
||||
|
||||
/**
|
||||
* Get all elements with lexicographical ordering from {@literal ZSET} at {@code key} with a value between
|
||||
* {@link Range#getLowerBound()} and {@link Range#getUpperBound()}.
|
||||
|
||||
@@ -555,8 +555,50 @@ public class LettuceReactiveZSetCommandsIntegrationTests extends LettuceReactive
|
||||
.isEqualTo(1L);
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-525
|
||||
void zUnionStoreShouldWorkCorrectly() {
|
||||
@ParameterizedRedisTest // GH-2041
|
||||
void zDiffShouldWorkCorrectly() {
|
||||
|
||||
assumeThat(connectionProvider).isInstanceOf(StandaloneConnectionProvider.class);
|
||||
|
||||
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
|
||||
nativeCommands.zadd(KEY_2, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_2, 2D, VALUE_2);
|
||||
|
||||
connection.zSetCommands().zDiff(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).containsOnly(VALUE_3_BBUFFER);
|
||||
}).verifyComplete();
|
||||
|
||||
connection.zSetCommands().zDiffWithScores(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).containsOnly(new DefaultTuple(VALUE_3_BYTES, 3D));
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2041
|
||||
void zDiffStoreShouldWorkCorrectly() {
|
||||
|
||||
assumeThat(connectionProvider).isInstanceOf(StandaloneConnectionProvider.class);
|
||||
|
||||
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_1, 3D, VALUE_3);
|
||||
nativeCommands.zadd(KEY_2, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_2, 2D, VALUE_2);
|
||||
|
||||
connection.zSetCommands().zDiffStore(KEY_3_BBUFFER, Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(1L).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2042
|
||||
void zInterShouldWorkCorrectly() {
|
||||
|
||||
assumeThat(connectionProvider).isInstanceOf(StandaloneConnectionProvider.class);
|
||||
|
||||
@@ -566,9 +608,19 @@ public class LettuceReactiveZSetCommandsIntegrationTests extends LettuceReactive
|
||||
nativeCommands.zadd(KEY_2, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_2, 3D, VALUE_3);
|
||||
|
||||
assertThat(connection.zSetCommands()
|
||||
.zUnionStore(KEY_3_BBUFFER, Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), Arrays.asList(2D, 3D)).block())
|
||||
.isEqualTo(3L);
|
||||
connection.zSetCommands().zInter(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).contains(VALUE_1_BBUFFER, VALUE_2_BBUFFER);
|
||||
}).verifyComplete();
|
||||
|
||||
connection.zSetCommands().zInterWithScores(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), Arrays.asList(2D, 3D)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).contains(new DefaultTuple(VALUE_1_BYTES, 5D), new DefaultTuple(VALUE_2_BYTES, 10D));
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-525
|
||||
@@ -587,6 +639,49 @@ public class LettuceReactiveZSetCommandsIntegrationTests extends LettuceReactive
|
||||
.isEqualTo(2L);
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2042
|
||||
void zUnionShouldWorkCorrectly() {
|
||||
|
||||
assumeThat(connectionProvider).isInstanceOf(StandaloneConnectionProvider.class);
|
||||
|
||||
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_2, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_2, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_2, 3D, VALUE_3);
|
||||
|
||||
connection.zSetCommands().zUnion(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).contains(VALUE_1_BBUFFER, VALUE_2_BBUFFER, VALUE_3_BBUFFER);
|
||||
}).verifyComplete();
|
||||
|
||||
connection.zSetCommands().zUnionWithScores(Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), Arrays.asList(2D, 3D)) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual).contains(new DefaultTuple(VALUE_1_BYTES, 5D), new DefaultTuple(VALUE_2_BYTES, 10D),
|
||||
new DefaultTuple(VALUE_3_BYTES, 9D));
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-525
|
||||
void zUnionStoreShouldWorkCorrectly() {
|
||||
|
||||
assumeThat(connectionProvider).isInstanceOf(StandaloneConnectionProvider.class);
|
||||
|
||||
nativeCommands.zadd(KEY_1, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_1, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_2, 1D, VALUE_1);
|
||||
nativeCommands.zadd(KEY_2, 2D, VALUE_2);
|
||||
nativeCommands.zadd(KEY_2, 3D, VALUE_3);
|
||||
|
||||
assertThat(connection.zSetCommands()
|
||||
.zUnionStore(KEY_3_BBUFFER, Arrays.asList(KEY_1_BBUFFER, KEY_2_BBUFFER), Arrays.asList(2D, 3D)).block())
|
||||
.isEqualTo(3L);
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-525
|
||||
void zRangeByLex() {
|
||||
|
||||
|
||||
@@ -559,6 +559,168 @@ public class DefaultReactiveZSetOperationsIntegrationTests<K, V> {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2041
|
||||
void difference() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.difference(key, otherKey).as(StepVerifier::create).expectNext(onlyInKey).verifyComplete();
|
||||
|
||||
zSetOperations.differenceWithScores(key, otherKey).as(StepVerifier::create)
|
||||
.expectNext(new DefaultTypedTuple<>(onlyInKey, 10D)).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2041
|
||||
void differenceAndStore() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
K destKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.differenceAndStore(key, otherKey, destKey).as(StepVerifier::create).expectNext(1L).verifyComplete();
|
||||
|
||||
zSetOperations.range(destKey, ZERO_TO_FIVE).as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2042
|
||||
@EnabledOnCommand("ZINTER")
|
||||
void intersect() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.intersect(key, otherKey).as(StepVerifier::create).expectNext(shared).verifyComplete();
|
||||
|
||||
zSetOperations.intersectWithScores(key, otherKey).as(StepVerifier::create)
|
||||
.expectNext(new DefaultTypedTuple<>(shared, 22D)).verifyComplete();
|
||||
|
||||
zSetOperations.intersectWithScores(key, Collections.singleton(otherKey), Aggregate.SUM, Weights.of(1, 2))
|
||||
.as(StepVerifier::create).expectNext(new DefaultTypedTuple<>(shared, 33D)).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-602
|
||||
void intersectAndStore() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
K destKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, otherKey, destKey).as(StepVerifier::create).expectNext(1L).expectComplete()
|
||||
.verify();
|
||||
|
||||
zSetOperations.range(destKey, ZERO_TO_FIVE).as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-746
|
||||
void intersectAndStoreWithAggregation() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
K destKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, Collections.singletonList(otherKey), destKey, Aggregate.SUM)
|
||||
.as(StepVerifier::create).expectNext(1L).expectComplete().verify();
|
||||
|
||||
zSetOperations.score(destKey, shared).as(StepVerifier::create) //
|
||||
.expectNext(22d) //
|
||||
.verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, Collections.singletonList(otherKey), destKey, Aggregate.SUM, Weights.of(1, 2))
|
||||
.as(StepVerifier::create).expectNext(1L).expectComplete().verify();
|
||||
|
||||
zSetOperations.score(destKey, shared).as(StepVerifier::create) //
|
||||
.expectNext(33d) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-2042
|
||||
@EnabledOnCommand("ZUNION")
|
||||
void union() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.union(key, otherKey).as(StepVerifier::create).expectNextCount(3).verifyComplete();
|
||||
|
||||
zSetOperations.unionWithScores(key, otherKey).collectList().as(StepVerifier::create).assertNext(actual -> {
|
||||
assertThat(actual).containsOnly(new DefaultTypedTuple<>(onlyInKey, 10D), new DefaultTypedTuple<>(shared, 22D),
|
||||
new DefaultTypedTuple<>(onlyInOtherKey, 10D));
|
||||
|
||||
}).verifyComplete();
|
||||
|
||||
zSetOperations.unionWithScores(key, Collections.singleton(otherKey), Aggregate.SUM, Weights.of(1, 2)).collectList()
|
||||
.as(StepVerifier::create).assertNext(actual -> {
|
||||
assertThat(actual).containsOnly(new DefaultTypedTuple<>(onlyInKey, 10D), new DefaultTypedTuple<>(shared, 33D),
|
||||
new DefaultTypedTuple<>(onlyInOtherKey, 20D));
|
||||
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-602
|
||||
void unionAndStore() {
|
||||
|
||||
@@ -607,64 +769,6 @@ public class DefaultReactiveZSetOperationsIntegrationTests<K, V> {
|
||||
zSetOperations.score(destKey, shared).as(StepVerifier::create).expectNext(33d).verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-602
|
||||
void intersectAndStore() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
K destKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, otherKey, destKey).as(StepVerifier::create).expectNext(1L).expectComplete()
|
||||
.verify();
|
||||
|
||||
zSetOperations.range(destKey, ZERO_TO_FIVE).as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-746
|
||||
void intersectAndStoreWithAggregation() {
|
||||
|
||||
K key = keyFactory.instance();
|
||||
K otherKey = keyFactory.instance();
|
||||
K destKey = keyFactory.instance();
|
||||
|
||||
V onlyInKey = valueFactory.instance();
|
||||
V shared = valueFactory.instance();
|
||||
V onlyInOtherKey = valueFactory.instance();
|
||||
|
||||
zSetOperations.add(key, onlyInKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(key, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.add(otherKey, onlyInOtherKey, 10).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
zSetOperations.add(otherKey, shared, 11).as(StepVerifier::create).expectNext(true).verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, Collections.singletonList(otherKey), destKey, Aggregate.SUM)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(1L).expectComplete().verify();
|
||||
|
||||
zSetOperations.score(destKey, shared).as(StepVerifier::create) //
|
||||
.expectNext(22d) //
|
||||
.verifyComplete();
|
||||
|
||||
zSetOperations.intersectAndStore(key, Collections.singletonList(otherKey), destKey, Aggregate.SUM, Weights.of(1, 2))
|
||||
.as(StepVerifier::create).expectNext(1L).expectComplete().verify();
|
||||
|
||||
zSetOperations.score(destKey, shared).as(StepVerifier::create) //
|
||||
.expectNext(33d) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // DATAREDIS-602
|
||||
void rangeByLex() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user