Add support for ZMSCORE through score(key, values).

We now support Redis 6.2 ZMSCORE through the Template API and on the connection level for all drivers.

Closes #2038
Original Pull Request: #2088
This commit is contained in:
Mark Paluch
2021-06-15 14:58:03 +02:00
committed by Christoph Strobl
parent c878a933f5
commit 8c743d40ef
29 changed files with 398 additions and 7 deletions

View File

@@ -1722,6 +1722,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
return convertAndReturn(delegate.zScore(key, value), Converters.identityConverter());
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zMScore(byte[], byte[][])
*/
@Override
public List<Double> zMScore(byte[] key, byte[]... values) {
return convertAndReturn(delegate.zMScore(key, values), Converters.identityConverter());
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zUnionStore(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, org.springframework.data.redis.connection.RedisZSetCommands.Weights, byte[][])
@@ -3052,6 +3061,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
return zScore(serialize(key), serialize(value));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#zMScore(java.lang.String, java.lang.String[])
*/
@Override
public List<Double> zMScore(String key, String... values) {
return zMScore(serialize(key), serializeMulti(values));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#zUnionStore(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Aggregate, int[], java.lang.String[])

View File

@@ -1103,6 +1103,13 @@ public interface DefaultedRedisConnection extends RedisConnection {
return zSetCommands().zScore(key, value);
}
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
@Override
@Deprecated
default List<Double> zMScore(byte[] key, byte[]... values) {
return zSetCommands().zMScore(key, values);
}
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
@Override
@Deprecated

View File

@@ -31,6 +31,7 @@ import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyScanCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
import org.springframework.data.redis.connection.RedisZSetCommands.Limit;
@@ -292,7 +293,7 @@ public interface ReactiveZSetCommands {
* Creates a new {@link ZRemCommand} given a {@link Tuple}.
*
* @param value must not be {@literal null}.
* @return a new {@link ZAddCommand} for {@link Tuple}.
* @return a new {@link ZRemCommand} for {@link Tuple}.
*/
public static ZRemCommand values(ByteBuffer value) {
@@ -305,7 +306,7 @@ public interface ReactiveZSetCommands {
* Creates a new {@link ZRemCommand} given a {@link Collection} of {@link Tuple}.
*
* @param values must not be {@literal null}.
* @return a new {@link ZAddCommand} for {@link Tuple}.
* @return a new {@link ZRemCommand} for {@link Tuple}.
*/
public static ZRemCommand values(Collection<ByteBuffer> values) {
@@ -1283,7 +1284,7 @@ public interface ReactiveZSetCommands {
* Creates a new {@link ZScoreCommand} given a {@link ByteBuffer member}.
*
* @param member must not be {@literal null}.
* @return a new {@link ZScoreCommand} for {@link Range}.
* @return a new {@link ZScoreCommand} for {@link ByteBuffer member}.
*/
public static ZScoreCommand scoreOf(ByteBuffer member) {
@@ -1339,6 +1340,99 @@ public interface ReactiveZSetCommands {
*/
Flux<NumericResponse<ZScoreCommand, Double>> zScore(Publisher<ZScoreCommand> commands);
/**
* {@code ZMSCORE} command parameters.
*
* @author Mark Paluch
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
class ZMScoreCommand extends KeyCommand {
private final Collection<ByteBuffer> values;
private ZMScoreCommand(@Nullable ByteBuffer key, Collection<ByteBuffer> values) {
super(key);
this.values = values;
}
/**
* Creates a new {@link ZMScoreCommand} given a {@link ByteBuffer member}.
*
* @param member must not be {@literal null}.
* @return a new {@link ZMScoreCommand} for {@link ByteBuffer}.
*/
public static ZMScoreCommand scoreOf(ByteBuffer member) {
Assert.notNull(member, "Member must not be null!");
return new ZMScoreCommand(null, Collections.singletonList(member));
}
/**
* Creates a new {@link ZMScoreCommand} given a {@link List members}.
*
* @param member must not be {@literal null}.
* @return a new {@link ZMScoreCommand} for {@link List} of members.
*/
public static ZMScoreCommand scoreOf(Collection<ByteBuffer> members) {
Assert.notNull(members, "Members must not be null!");
return new ZMScoreCommand(null, members);
}
/**
* 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 ZMScoreCommand} with {@literal key} applied.
*/
public ZMScoreCommand forKey(ByteBuffer key) {
Assert.notNull(key, "Key must not be null!");
return new ZMScoreCommand(key, values);
}
/**
* @return
*/
public Collection<ByteBuffer> getValues() {
return values;
}
}
/**
* Get the scores of elements with {@literal values} from sorted set with key {@literal key}.
*
* @param key must not be {@literal null}.
* @param values must not be {@literal null}.
* @return
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
default Mono<List<Double>> zMScore(ByteBuffer key, Collection<ByteBuffer> values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Values must not be null!");
return zMScore(Mono.just(ZMScoreCommand.scoreOf(values).forKey(key))).next().map(MultiValueResponse::getOutput);
}
/**
* Get the scores of elements with {@link ZMScoreCommand#getValues()} from sorted set with key
* {@link ZMScoreCommand#getKey()}
*
* @param commands must not be {@literal null}.
* @return
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
Flux<MultiValueResponse<ZMScoreCommand, Double>> zMScore(Publisher<ZMScoreCommand> commands);
/**
* {@code ZREMRANGEBYRANK} command parameters.
*
@@ -1787,7 +1881,7 @@ public interface ReactiveZSetCommands {
* Creates a new {@link ZInterStoreCommand} given a {@link List} of keys.
*
* @param keys must not be {@literal null}.
* @return a new {@link ZInterStoreCommand} for {@link Range}.
* @return a new {@link ZInterStoreCommand} for {@link List} of keys.
*/
public static ZInterStoreCommand sets(List<ByteBuffer> keys) {

View File

@@ -993,6 +993,18 @@ public interface RedisZSetCommands {
@Nullable
Double zScore(byte[] key, byte[] value);
/**
* Get the scores of elements with {@code values} from sorted set with key {@code key}.
*
* @param key must not be {@literal null}.
* @param values the values.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
@Nullable
List<Double> zMScore(byte[] key, byte[]... values);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with {@code key}.
*

View File

@@ -1455,6 +1455,18 @@ public interface StringRedisConnection extends RedisConnection {
*/
Double zScore(String key, String value);
/**
* Get the scores of elements with {@code values} from sorted set with key {@code key}.
*
* @param key must not be {@literal null}.
* @param values the values.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @see RedisZSetCommands#zMScore(byte[], byte[][])
* @since 2.6
*/
List<Double> zMScore(String key, String... values);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with {@code key}.
*

View File

@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection.jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ZParams;
import java.util.List;
import java.util.Set;
import org.springframework.dao.DataAccessException;
@@ -637,6 +638,23 @@ class JedisClusterZSetCommands implements RedisZSetCommands {
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zMScore(byte[], byte[][])
*/
@Override
public List<Double> zMScore(byte[] key, byte[][] values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Values must not be null!");
try {
return connection.getCluster().zmscore(key, values);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)

View File

@@ -21,14 +21,13 @@ import redis.clients.jedis.MultiKeyPipelineBase;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import redis.clients.jedis.ZParams;
import redis.clients.jedis.params.ZAddParams;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs.Flag;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.KeyBoundCursor;
import org.springframework.data.redis.core.ScanIteration;
@@ -323,6 +322,19 @@ class JedisZSetCommands implements RedisZSetCommands {
return connection.invoke().just(BinaryJedis::zscore, MultiKeyPipelineBase::zscore, key, value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zScore(byte[], byte[][])
*/
@Override
public List<Double> zMScore(byte[] key, byte[][] values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Value must not be null!");
return connection.invoke().just(BinaryJedis::zmscore, MultiKeyPipelineBase::zmscore, key, values);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)

View File

@@ -1209,6 +1209,9 @@ public class LettuceConnection extends AbstractRedisConnection {
COMMAND_OUTPUT_TYPE_MAPPING.put(ZINCRBY, DoubleOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(ZSCORE, DoubleOutput.class);
// DOUBLE LIST
COMMAND_OUTPUT_TYPE_MAPPING.put(ZMSCORE, DoubleListOutput.class);
// MAP
COMMAND_OUTPUT_TYPE_MAPPING.put(HGETALL, MapOutput.class);
@@ -1281,6 +1284,7 @@ public class LettuceConnection extends AbstractRedisConnection {
COMMAND_OUTPUT_TYPE_MAPPING.put(HSET, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(HSETNX, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(MOVE, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(COPY, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(MSETNX, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(PERSIST, BooleanOutput.class);
COMMAND_OUTPUT_TYPE_MAPPING.put(PEXPIRE, BooleanOutput.class);

View File

@@ -27,11 +27,13 @@ import java.nio.ByteBuffer;
import java.util.List;
import org.reactivestreams.Publisher;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.redis.connection.DefaultTuple;
import org.springframework.data.redis.connection.ReactiveRedisConnection.CommandResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.KeyScanCommand;
import org.springframework.data.redis.connection.ReactiveRedisConnection.MultiValueResponse;
import org.springframework.data.redis.connection.ReactiveRedisConnection.NumericResponse;
import org.springframework.data.redis.connection.ReactiveZSetCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
@@ -381,6 +383,23 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zMScore(org.reactivestreams.Publisher)
*/
@Override
public Flux<MultiValueResponse<ZMScoreCommand, Double>> zMScore(Publisher<ZMScoreCommand> commands) {
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
Assert.notNull(command.getKey(), "Key must not be null!");
Assert.notNull(command.getValues(), "Values must not be null!");
return cmd.zmscore(command.getKey(), command.getValues().toArray(new ByteBuffer[0]))
.map(value -> new MultiValueResponse<>(command, value));
}));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.ReactiveZSetCommands#zRemRangeByRank(org.reactivestreams.Publisher)

View File

@@ -302,6 +302,19 @@ class LettuceZSetCommands implements RedisZSetCommands {
return connection.invoke().just(RedisSortedSetAsyncCommands::zscore, key, value);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zMScore(byte[], byte[][])
*/
@Override
public List<Double> zMScore(byte[] key, byte[][] values) {
Assert.notNull(key, "Key must not be null!");
Assert.notNull(values, "Value must not be null!");
return connection.invoke().just(RedisSortedSetAsyncCommands::zmscore, key, values);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRemRange(byte[], long, long)

View File

@@ -16,6 +16,7 @@
package org.springframework.data.redis.core;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
@@ -264,6 +265,17 @@ public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
@Nullable
Double score(Object o);
/**
* Get the scores of elements with {@code values} from sorted set with key the bound key.
*
* @param o the values.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
@Nullable
List<Double> score(Object... o);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with the bound key.
*

View File

@@ -17,6 +17,7 @@
package org.springframework.data.redis.core;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.springframework.data.redis.connection.DataType;
@@ -249,6 +250,15 @@ class DefaultBoundZSetOperations<K, V> extends DefaultBoundKeyOperations<K> impl
return ops.score(getKey(), o);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.BoundZSetOperations#score(java.lang.Object[])
*/
@Override
public List<Double> score(Object... o) {
return ops.score(getKey(), o);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.BoundZSetOperations#remove(java.lang.Object[])

View File

@@ -370,6 +370,22 @@ class DefaultReactiveZSetOperations<K, V> implements ReactiveZSetOperations<K, V
return createMono(connection -> connection.zScore(rawKey(key), rawValue((V) o)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveZSetOperations#score(java.lang.Object, java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public Mono<List<Double>> score(K key, Object... o) {
Assert.notNull(key, "Key must not be null!");
return createMono(connection -> Flux.fromArray((V[]) o) //
.map(this::rawValue) //
.collectList() //
.flatMap(values -> connection.zMScore(rawKey(key), values)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ReactiveZSetOperations#removeRange(java.lang.Object, org.springframework.data.domain.Range)

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.core;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
@@ -437,6 +438,18 @@ class DefaultZSetOperations<K, V> extends AbstractOperations<K, V> implements ZS
return execute(connection -> connection.zScore(rawKey, rawValue), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ZSetOperations#score(java.lang.Object, java.lang.Object[])
*/
@Override
public List<Double> score(K key, Object... o) {
byte[] rawKey = rawKey(key);
byte[][] rawValues = rawValues(o);
return execute(connection -> connection.zMScore(rawKey, rawValues), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.ZSetOperations#count(java.lang.Object, double, double)

View File

@@ -19,6 +19,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collection;
import java.util.List;
import org.springframework.data.domain.Range;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
@@ -300,6 +301,17 @@ public interface ReactiveZSetOperations<K, V> {
*/
Mono<Double> score(K key, Object o);
/**
* Get the scores of elements with {@code values} from sorted set with key {@code key}.
*
* @param key must not be {@literal null}.
* @param o the values.
* @return
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
Mono<List<Double>> score(K key, Object... o);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with {@code key}.
*

View File

@@ -16,6 +16,7 @@
package org.springframework.data.redis.core;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
@@ -370,6 +371,18 @@ public interface ZSetOperations<K, V> {
@Nullable
Double score(K key, Object o);
/**
* Get the scores of elements with {@code values} from sorted set with key {@code key}.
*
* @param key must not be {@literal null}.
* @param o the values.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/zmscore">Redis Documentation: ZMSCORE</a>
* @since 2.6
*/
@Nullable
List<Double> score(K key, Object... o);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with {@code key}.
*