From 7755da8cd587499dc319f897d0d6fbff5a470804 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 4 Mar 2021 11:08:15 +0100 Subject: [PATCH] Add support for HRANDFIELD and ZRANDMEMBER commands #1605 --- .../core/AbstractRedisAsyncCommands.java | 40 ++++++ .../core/AbstractRedisReactiveCommands.java | 40 ++++++ .../io/lettuce/core/RedisCommandBuilder.java | 60 +++++++++ .../api/async/RedisHashAsyncCommands.java | 49 ++++++- .../async/RedisSortedSetAsyncCommands.java | 53 +++++++- .../reactive/RedisHashReactiveCommands.java | 50 ++++++- .../RedisSortedSetReactiveCommands.java | 53 +++++++- .../core/api/sync/RedisHashCommands.java | 50 ++++++- .../core/api/sync/RedisSortedSetCommands.java | 53 +++++++- .../async/NodeSelectionHashAsyncCommands.java | 48 ++++++- .../NodeSelectionSortedSetAsyncCommands.java | 51 ++++++- .../api/sync/NodeSelectionHashCommands.java | 48 ++++++- .../sync/NodeSelectionSortedSetCommands.java | 51 ++++++- .../lettuce/core/protocol/CommandKeyword.java | 2 +- .../io/lettuce/core/protocol/CommandType.java | 4 +- .../coroutines/RedisHashCoroutinesCommands.kt | 40 +++++- .../RedisHashCoroutinesCommandsImpl.kt | 36 ++++- .../RedisSortedSetCoroutinesCommands.kt | 127 ++++++++++++------ .../RedisSortedSetCoroutinesCommandsImpl.kt | 41 ++++-- .../lettuce/core/api/RedisHashCommands.java | 43 +++++- .../core/api/RedisSortedSetCommands.java | 39 ++++++ .../commands/HashCommandIntegrationTests.java | 29 +++- .../SortedSetCommandIntegrationTests.java | 14 ++ .../StreamCommandIntegrationTests.java | 11 +- 24 files changed, 918 insertions(+), 114 deletions(-) diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index d245520ba1..6a6e400b54 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -899,6 +899,26 @@ public RedisFuture hmset(K key, Map map) { return dispatch(commandBuilder.hmset(key, map)); } + @Override + public RedisFuture hrandfield(K key) { + return dispatch(commandBuilder.hrandfield(key)); + } + + @Override + public RedisFuture> hrandfield(K key, long count) { + return dispatch(commandBuilder.hrandfield(key, count)); + } + + @Override + public RedisFuture> hrandfieldWithvalues(K key) { + return dispatch(commandBuilder.hrandfieldWithvalues(key)); + } + + @Override + public RedisFuture>> hrandfieldWithvalues(K key, long count) { + return dispatch(commandBuilder.hrandfieldWithvalues(key, count)); + } + @Override public RedisFuture> hscan(K key) { return dispatch(commandBuilder.hscan(key)); @@ -2053,6 +2073,26 @@ public RedisFuture>> zpopmax(K key, long count) { return dispatch(commandBuilder.zpopmax(key, count)); } + @Override + public RedisFuture zrandmember(K key) { + return dispatch(commandBuilder.zrandmember(key)); + } + + @Override + public RedisFuture> zrandmember(K key, long count) { + return dispatch(commandBuilder.zrandmember(key, count)); + } + + @Override + public RedisFuture> zrandmemberWithscores(K key) { + return dispatch(commandBuilder.zrandmemberWithscores(key)); + } + + @Override + public RedisFuture>> zrandmemberWithscores(K key, long count) { + return dispatch(commandBuilder.zrandmemberWithscores(key, count)); + } + @Override public RedisFuture> zrange(K key, long start, long stop) { return dispatch(commandBuilder.zrange(key, start, stop)); diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index 37713bf93f..5de7515315 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -955,6 +955,26 @@ public Mono hmget(KeyValueStreamingChannel channel, K key, K... fiel return createMono(() -> commandBuilder.hmget(channel, key, fields)); } + @Override + public Mono hrandfield(K key) { + return createMono(() -> commandBuilder.hrandfield(key)); + } + + @Override + public Flux hrandfield(K key, long count) { + return createDissolvingFlux(() -> commandBuilder.hrandfield(key, count)); + } + + @Override + public Mono> hrandfieldWithvalues(K key) { + return createMono(() -> commandBuilder.hrandfieldWithvalues(key)); + } + + @Override + public Flux> hrandfieldWithvalues(K key, long count) { + return createDissolvingFlux(() -> commandBuilder.hrandfieldWithvalues(key, count)); + } + @Override public Mono hmset(K key, Map map) { return createMono(() -> commandBuilder.hmset(key, map)); @@ -2126,6 +2146,26 @@ public Flux> zpopmax(K key, long count) { return createDissolvingFlux(() -> commandBuilder.zpopmax(key, count)); } + @Override + public Mono zrandmember(K key) { + return createMono(() -> commandBuilder.zrandmember(key)); + } + + @Override + public Flux zrandmember(K key, long count) { + return createDissolvingFlux(() -> commandBuilder.zrandmember(key, count)); + } + + @Override + public Mono> zrandmemberWithscores(K key) { + return createMono(() -> commandBuilder.zrandmemberWithscores(key)); + } + + @Override + public Flux> zrandmemberWithscores(K key, long count) { + return createDissolvingFlux(() -> commandBuilder.zrandmemberWithscores(key, count)); + } + @Override public Flux zrange(K key, long start, long stop) { return createDissolvingFlux(() -> commandBuilder.zrange(key, start, stop)); diff --git a/src/main/java/io/lettuce/core/RedisCommandBuilder.java b/src/main/java/io/lettuce/core/RedisCommandBuilder.java index 9f7e124a78..6325e34974 100644 --- a/src/main/java/io/lettuce/core/RedisCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RedisCommandBuilder.java @@ -1207,6 +1207,34 @@ Command hmset(K key, Map map) { return createCommand(HMSET, new StatusOutput<>(codec), args); } + Command hrandfield(K key) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKey(key); + return createCommand(HRANDFIELD, new KeyOutput<>(codec), args); + } + + Command> hrandfield(K key, long count) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKey(key).add(count); + return createCommand(HRANDFIELD, new KeyListOutput<>(codec), args); + } + + Command> hrandfieldWithvalues(K key) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKey(key).add(1).add(WITHVALUES); + return createCommand(HRANDFIELD, new KeyValueOutput<>(codec), args); + } + + Command>> hrandfieldWithvalues(K key, long count) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKey(key).add(count).add(WITHVALUES); + return createCommand(HRANDFIELD, new KeyValueListOutput<>(codec), args); + } + Command> hscan(K key) { notNullKey(key); @@ -2987,6 +3015,38 @@ Command>> zpopmax(K key, long count) { return createCommand(ZPOPMAX, new ScoredValueListOutput<>(codec), args); } + Command zrandmember(K key) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKeys(key); + + return createCommand(ZRANDMEMBER, new ValueOutput<>(codec), args); + } + + Command> zrandmember(K key, long count) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKeys(key).add(count); + + return createCommand(ZRANDMEMBER, new ValueListOutput<>(codec), args); + } + + Command> zrandmemberWithscores(K key) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKeys(key).add(1).add(WITHSCORES); + + return createCommand(ZRANDMEMBER, new ScoredValueOutput<>(codec), args); + } + + Command>> zrandmemberWithscores(K key, long count) { + notNullKey(key); + + CommandArgs args = new CommandArgs<>(codec).addKeys(key).add(count).add(WITHSCORES); + + return createCommand(ZRANDMEMBER, new ScoredValueListOutput<>(codec), args); + } + Command> zrange(K key, long start, long stop) { notNullKey(key); diff --git a/src/main/java/io/lettuce/core/api/async/RedisHashAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RedisHashAsyncCommands.java index c60ff077e9..7c6f5806d3 100644 --- a/src/main/java/io/lettuce/core/api/async/RedisHashAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RedisHashAsyncCommands.java @@ -18,7 +18,12 @@ import java.util.List; import java.util.Map; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.RedisFuture; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -152,11 +157,51 @@ public interface RedisHashAsyncCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ RedisFuture hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + RedisFuture hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + RedisFuture> hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @return array-reply the key and value. + * @since 6.1 + */ + RedisFuture> hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + RedisFuture>> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java index 206f61b4d6..88b3d31b4d 100644 --- a/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java @@ -364,6 +364,48 @@ public interface RedisSortedSetAsyncCommands { */ RedisFuture>> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + RedisFuture zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + RedisFuture> zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return the score and element. + * @since 6.1 + */ + RedisFuture> zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + RedisFuture>> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * @@ -1238,8 +1280,8 @@ public interface RedisSortedSetAsyncCommands { * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores * the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * @param srcKey the dst key. * @param range the lexicographical range. * @return The number of elements in the resulting sorted set. * @since 6.1 @@ -1247,11 +1289,12 @@ public interface RedisSortedSetAsyncCommands { RedisFuture zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit); /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and * stores the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * + * @param srcKey the dst key. * @param range the score range. * @return The number of elements in the resulting sorted set. * @since 6.1 diff --git a/src/main/java/io/lettuce/core/api/reactive/RedisHashReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RedisHashReactiveCommands.java index b9fd053803..c1f517a0c4 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RedisHashReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RedisHashReactiveCommands.java @@ -19,7 +19,11 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -159,11 +163,53 @@ public interface RedisHashReactiveCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ Mono hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + Mono hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + Flux hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the key and value. + * @since 6.1 + */ + Mono> hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + Flux> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java index f6f087119b..a66050a09e 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java @@ -366,6 +366,48 @@ public interface RedisSortedSetReactiveCommands { */ Flux> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + Mono zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return ScoredValue<V> array-reply list of scores and elements. + * @since 6.1 + */ + Flux zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return the score and element. + * @since 6.1 + */ + Mono> zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return ScoredValue<V> array-reply list of scores and elements. + * @since 6.1 + */ + Flux> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * @@ -1280,8 +1322,8 @@ public interface RedisSortedSetReactiveCommands { * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores * the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * @param srcKey the dst key. * @param range the lexicographical range. * @return The number of elements in the resulting sorted set. * @since 6.1 @@ -1289,11 +1331,12 @@ public interface RedisSortedSetReactiveCommands { Mono zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit); /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and * stores the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * + * @param srcKey the dst key. * @param range the score range. * @return The number of elements in the resulting sorted set. * @since 6.1 diff --git a/src/main/java/io/lettuce/core/api/sync/RedisHashCommands.java b/src/main/java/io/lettuce/core/api/sync/RedisHashCommands.java index 3f92171fb6..cf36094797 100644 --- a/src/main/java/io/lettuce/core/api/sync/RedisHashCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RedisHashCommands.java @@ -18,7 +18,11 @@ import java.util.List; import java.util.Map; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -152,11 +156,53 @@ public interface RedisHashCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ String hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + K hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + List hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the key and value. + * @since 6.1 + */ + KeyValue hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + List> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java b/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java index f2653749ce..dcd5149abe 100644 --- a/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java @@ -364,6 +364,48 @@ public interface RedisSortedSetCommands { */ List> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + V zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + List zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return the score and element. + * @since 6.1 + */ + ScoredValue zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + List> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * @@ -1238,8 +1280,8 @@ public interface RedisSortedSetCommands { * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores * the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * @param srcKey the dst key. * @param range the lexicographical range. * @return The number of elements in the resulting sorted set. * @since 6.1 @@ -1247,11 +1289,12 @@ public interface RedisSortedSetCommands { Long zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit); /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and * stores the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * + * @param srcKey the dst key. * @param range the score range. * @return The number of elements in the resulting sorted set. * @since 6.1 diff --git a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionHashAsyncCommands.java b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionHashAsyncCommands.java index b2c0d5dc50..5185896e03 100644 --- a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionHashAsyncCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionHashAsyncCommands.java @@ -18,7 +18,11 @@ import java.util.List; import java.util.Map; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -152,11 +156,51 @@ public interface NodeSelectionHashAsyncCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ AsyncExecutions hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + AsyncExecutions hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + AsyncExecutions> hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @return array-reply the key and value. + * @since 6.1 + */ + AsyncExecutions> hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + AsyncExecutions>> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionSortedSetAsyncCommands.java b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionSortedSetAsyncCommands.java index 91267d6e37..f851ecdc2f 100644 --- a/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionSortedSetAsyncCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionSortedSetAsyncCommands.java @@ -364,6 +364,46 @@ public interface NodeSelectionSortedSetAsyncCommands { */ AsyncExecutions>> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + AsyncExecutions zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + AsyncExecutions> zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @return the score and element. + * @since 6.1 + */ + AsyncExecutions> zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + AsyncExecutions>> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * @@ -1238,8 +1278,8 @@ public interface NodeSelectionSortedSetAsyncCommands { * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores * the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * @param srcKey the dst key. * @param range the lexicographical range. * @return The number of elements in the resulting sorted set. * @since 6.1 @@ -1247,11 +1287,12 @@ public interface NodeSelectionSortedSetAsyncCommands { AsyncExecutions zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit); /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and * stores the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * + * @param srcKey the dst key. * @param range the score range. * @return The number of elements in the resulting sorted set. * @since 6.1 diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionHashCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionHashCommands.java index 472cb10bcb..49a919c030 100644 --- a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionHashCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionHashCommands.java @@ -18,7 +18,11 @@ import java.util.List; import java.util.Map; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -152,11 +156,51 @@ public interface NodeSelectionHashCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ Executions hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + Executions hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + Executions> hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @return array-reply the key and value. + * @since 6.1 + */ + Executions> hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + Executions>> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionSortedSetCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionSortedSetCommands.java index 3f1de597b2..b398ae8aca 100644 --- a/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionSortedSetCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionSortedSetCommands.java @@ -364,6 +364,46 @@ public interface NodeSelectionSortedSetCommands { */ Executions>> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + Executions zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + Executions> zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @return the score and element. + * @since 6.1 + */ + Executions> zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + Executions>> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * @@ -1238,8 +1278,8 @@ public interface NodeSelectionSortedSetCommands { * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores * the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * @param srcKey the dst key. * @param range the lexicographical range. * @return The number of elements in the resulting sorted set. * @since 6.1 @@ -1247,11 +1287,12 @@ public interface NodeSelectionSortedSetCommands { Executions zrevrangestorebylex(K dstKey, K srcKey, Range range, Limit limit); /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and * stores the result in the {@code dstKey} destination key. * - * @param dstKey the dst key. - * @param srcKey the src key. + * @param dstKey the src key. + * + * @param srcKey the dst key. * @param range the score range. * @return The number of elements in the resulting sorted set. * @since 6.1 diff --git a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java index 776ea21b79..bac7798098 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java +++ b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java @@ -43,7 +43,7 @@ public enum CommandKeyword implements ProtocolKeyword { MIGRATING, IMPORTING, SAVE, SKIPME, SLAVES, STREAM, STORE, SUM, SEGFAULT, SETUSER, TRACKING, TYPE, UNBLOCK, USERS, WEIGHTS, WHOAMI, - WITHSCORES, XOR, YES, USAGE; + WITHSCORES, WITHVALUES, XOR, YES, USAGE; public final byte[] bytes; diff --git a/src/main/java/io/lettuce/core/protocol/CommandType.java b/src/main/java/io/lettuce/core/protocol/CommandType.java index edf8f3c8bc..9ee9a9acfa 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandType.java +++ b/src/main/java/io/lettuce/core/protocol/CommandType.java @@ -58,7 +58,7 @@ public enum CommandType implements ProtocolKeyword { // Hash - HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HSTRLEN, HMGET, HMSET, HSET, HSETNX, HVALS, HSCAN, + HDEL, HEXISTS, HGET, HGETALL, HINCRBY, HINCRBYFLOAT, HKEYS, HLEN, HSTRLEN, HMGET, HMSET, HRANDFIELD, HSET, HSETNX, HVALS, HSCAN, // Transaction @@ -78,7 +78,7 @@ public enum CommandType implements ProtocolKeyword { // Sorted Set - BZPOPMIN, BZPOPMAX, ZADD, ZCARD, ZCOUNT, ZDIFF, ZDIFFSTORE, ZINCRBY, ZINTER, ZINTERSTORE, ZLEXCOUNT, ZMSCORE, ZPOPMIN, ZPOPMAX, ZRANGE, ZRANGEBYSCORE, ZRANGESTORE, ZRANK, ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, ZREVRANGEBYSCORE, ZREVRANK, ZSCAN, ZSCORE, ZUNION, ZUNIONSTORE, ZREMRANGEBYLEX, ZRANGEBYLEX, + BZPOPMIN, BZPOPMAX, ZADD, ZCARD, ZCOUNT, ZDIFF, ZDIFFSTORE, ZINCRBY, ZINTER, ZINTERSTORE, ZLEXCOUNT, ZMSCORE, ZPOPMIN, ZPOPMAX, ZRANDMEMBER, ZRANGE, ZRANGEBYSCORE, ZRANGESTORE, ZRANK, ZREM, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX, ZREVRANGEBYSCORE, ZREVRANK, ZSCAN, ZSCORE, ZUNION, ZUNIONSTORE, ZREMRANGEBYLEX, ZRANGEBYLEX, // Scripting diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommands.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommands.kt index 2e88c18e46..a04a4cd543 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommands.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommands.kt @@ -121,11 +121,49 @@ interface RedisHashCoroutinesCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ suspend fun hmset(key: K, map: Map): String? + /** + * Return a random field from the hash stored at `key`. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + suspend fun hrandfield(key: K): K? + + /** + * Return `count` random fields from the hash stored at `key`. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct fields. + * @return array-reply list of field names. + * @since 6.1 + */ + suspend fun hrandfield(key: K, count: Long): List + + /** + * Return a random field along its value from the hash stored at `key`. + * + * @param key the key. + * @return array-reply the key and value. + * @since 6.1 + */ + suspend fun hrandfieldWithvalues(key: K): KeyValue? + + /** + * Return `count` random fields along their value from the hash stored at `key`. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + suspend fun hrandfieldWithvalues(key: K, count: Long): List> + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommandsImpl.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommandsImpl.kt index ba23026a1c..a09244ab19 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommandsImpl.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisHashCoroutinesCommandsImpl.kt @@ -19,6 +19,7 @@ package io.lettuce.core.api.coroutines import io.lettuce.core.* import io.lettuce.core.api.reactive.RedisHashReactiveCommands import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.asFlow import kotlinx.coroutines.reactive.awaitFirstOrNull @@ -42,7 +43,8 @@ internal class RedisHashCoroutinesCommandsImpl(internal val op override suspend fun hincrby(key: K, field: K, amount: Long): Long? = ops.hincrby(key, field, amount).awaitFirstOrNull() - override suspend fun hincrbyfloat(key: K, field: K, amount: Double): Double? = ops.hincrbyfloat(key, field, amount).awaitFirstOrNull() + override suspend fun hincrbyfloat(key: K, field: K, amount: Double): Double? = + ops.hincrbyfloat(key, field, amount).awaitFirstOrNull() override fun hgetall(key: K): Flow> = ops.hgetall(key).asFlow() @@ -50,17 +52,37 @@ internal class RedisHashCoroutinesCommandsImpl(internal val op override suspend fun hlen(key: K): Long? = ops.hlen(key).awaitFirstOrNull() - override fun hmget(key: K, vararg fields: K): Flow> = ops.hmget(key, *fields).asFlow() + override fun hmget(key: K, vararg fields: K): Flow> = + ops.hmget(key, *fields).asFlow() - override suspend fun hmset(key: K, map: Map): String? = ops.hmset(key, map).awaitFirstOrNull() + override suspend fun hrandfield(key: K): K? = ops.hrandfield(key).awaitFirstOrNull(); - override suspend fun hscan(key: K): MapScanCursor? = ops.hscan(key).awaitFirstOrNull() + override suspend fun hrandfield(key: K, count: Long): List = + ops.hrandfield(key, count).asFlow().toList() - override suspend fun hscan(key: K, scanArgs: ScanArgs): MapScanCursor? = ops.hscan(key, scanArgs).awaitFirstOrNull() + override suspend fun hrandfieldWithvalues(key: K): KeyValue? = + ops.hrandfieldWithvalues(key).awaitFirstOrNull(); - override suspend fun hscan(key: K, scanCursor: ScanCursor, scanArgs: ScanArgs): MapScanCursor? = ops.hscan(key, scanCursor, scanArgs).awaitFirstOrNull() + override suspend fun hrandfieldWithvalues(key: K, count: Long): List> = + ops.hrandfieldWithvalues(key, count).asFlow().toList() - override suspend fun hscan(key: K, scanCursor: ScanCursor): MapScanCursor? = ops.hscan(key, scanCursor).awaitFirstOrNull() + override suspend fun hmset(key: K, map: Map): String? = + ops.hmset(key, map).awaitFirstOrNull() + + override suspend fun hscan(key: K): MapScanCursor? = + ops.hscan(key).awaitFirstOrNull() + + override suspend fun hscan(key: K, scanArgs: ScanArgs): MapScanCursor? = + ops.hscan(key, scanArgs).awaitFirstOrNull() + + override suspend fun hscan( + key: K, + scanCursor: ScanCursor, + scanArgs: ScanArgs + ): MapScanCursor? = ops.hscan(key, scanCursor, scanArgs).awaitFirstOrNull() + + override suspend fun hscan(key: K, scanCursor: ScanCursor): MapScanCursor? = + ops.hscan(key, scanCursor).awaitFirstOrNull() override suspend fun hset(key: K, field: K, value: V): Boolean? = ops.hset(key, field, value).awaitFirstOrNull() diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt index bb7e59ca10..a68f8118a3 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt @@ -175,29 +175,29 @@ interface RedisSortedSetCoroutinesCommands { /** * Computes the difference between the first and all successive input sorted sets. - * - * @param keys the keys. - * @return List array-reply list of elements. - * @since 6.1 + * + * @param keys the keys. + * @return List array-reply list of elements. + * @since 6.1 */ fun zdiff(vararg keys: K): Flow /** - * Computes the difference between the first and all successive input sorted sets and stores the result in destination. - * - * @param destKey the dest key. - * @param srcKeys the src keys. - * @return Long the number of elements in the resulting sorted set at destination. - * @since 6.1 + * Computes the difference between the first and all successive input sorted sets and stores the result in destination. + * + * @param destKey the dest key. + * @param srcKeys the src keys. + * @return Long the number of elements in the resulting sorted set at destination. + * @since 6.1 */ suspend fun zdiffstore(destKey: K, vararg srcKeys: K): Long? /** - * Computes the difference between the first and all successive input sorted sets. - * - * @param keys the keys. - * @return List array-reply list of scored values. - * @since 6.1 + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List array-reply list of scored values. + * @since 6.1 */ fun zdiffWithScores(vararg keys: K): Flow> @@ -287,7 +287,7 @@ interface RedisSortedSetCoroutinesCommands { * * @param key the key. * @param members the member type: value. - * @return List array-reply list of scores or nil associated with the specified member values. + * @return List array-reply list of scores or nil associated with the specified member values. * @since 6.1 */ suspend fun zmscore(key: K, vararg members: V): List @@ -330,6 +330,45 @@ interface RedisSortedSetCoroutinesCommands { */ fun zpopmax(key: K, count: Long): Flow> + /** + * Return a random member from the sorted set stored at `key`. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + suspend fun zrandmember(key: K): V? + + /** + * Return `count` random members from the sorted set stored at `key`. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return List> array-reply list of scores and elements. + * @since 6.1 + */ + suspend fun zrandmember(key: K, count: Long): List + + /** + * Return a random member along its value from the sorted set stored at `key`. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return the score and element. + * @since 6.1 + */ + suspend fun zrandmemberWithscores(key: K): ScoredValue? + + /** + * Return `count` random members along their value from the sorted set stored at `key`. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return List> array-reply list of scores and elements. + * @since 6.1 + */ + suspend fun zrandmemberWithscores(key: K, count: Long): List> + /** * Return a range of members in a sorted set, by index. * @@ -414,24 +453,24 @@ interface RedisSortedSetCoroutinesCommands { fun zrangebyscoreWithScores(key: K, range: Range, limit: Limit): Flow> /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} and stores the result in the {@code dstKey} destination key. - * - * @param dstKey the dst key. - * @param srcKey the src key. - * @param range the lexicographical range. - * @return The number of elements in the resulting sorted set. - * @since 6.1 + * Get the specified range of elements in the sorted set stored at `srcKey` and stores the result in the `dstKey` destination key. + * + * @param dstKey the dst key. + * @param srcKey the src key. + * @param range the lexicographical range. + * @return The number of elements in the resulting sorted set. + * @since 6.1 */ suspend fun zrangestorebylex(dstKey: K, srcKey: K, range: Range, limit: Limit): Long? /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} and stores the result in the {@code dstKey} destination key. - * - * @param dstKey the dst key. - * @param srcKey the src key. - * @param range the score range. - * @return The number of elements in the resulting sorted set. - * @since 6.1 + * Get the specified range of elements in the sorted set stored at `srcKey` and stores the result in the `dstKey` destination key. + * + * @param dstKey the dst key. + * @param srcKey the src key. + * @param range the score range. + * @return The number of elements in the resulting sorted set. + * @since 6.1 */ suspend fun zrangestorebyscore(dstKey: K, srcKey: K, range: Range, limit: Limit): Long? @@ -570,24 +609,24 @@ interface RedisSortedSetCoroutinesCommands { fun zrevrangebyscoreWithScores(key: K, range: Range, limit: Limit): Flow> /** - * Get the lexicographical range ordered from high to low of elements in the sorted set stored at {@code srcKey} and stores the result in the {@code dstKey} destination key. - * - * @param dstKey the src key. - * @param srcKey the dst key. - * @param range the lexicographical range. - * @return The number of elements in the resulting sorted set. - * @since 6.1 + * Get the lexicographical range ordered from high to low of elements in the sorted set stored at `srcKey` and stores the result in the `dstKey` destination key. + * + * @param dstKey the src key. + * @param srcKey the dst key. + * @param range the lexicographical range. + * @return The number of elements in the resulting sorted set. + * @since 6.1 */ suspend fun zrevrangestorebylex(dstKey: K, srcKey: K, range: Range, limit: Limit): Long? /** - * Get the specified range of elements in the sorted set stored at {@code srcKey} with scores ordered from high to low and stores the result in the {@code dstKey} destination key. - * - * @param dstKey the src key. - * @param srcKey the dst key. - * @param range the score range. - * @return The number of elements in the resulting sorted set. - * @since 6.1 + * Get the specified range of elements in the sorted set stored at {@code srcKey with scores ordered from high to low and stores the result in the `dstKey` destination key. + * + * @param dstKey the src key. + * @param srcKey the dst key. + * @param range the score range. + * @return The number of elements in the resulting sorted set. + * @since 6.1 */ suspend fun zrevrangestorebyscore(dstKey: K, srcKey: K, range: Range, limit: Limit): Long? diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt index 0a2f1a6079..b8f17102e4 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt @@ -19,6 +19,7 @@ package io.lettuce.core.api.coroutines import io.lettuce.core.* import io.lettuce.core.api.reactive.RedisSortedSetReactiveCommands import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.asFlow import kotlinx.coroutines.reactive.awaitFirstOrNull @@ -94,23 +95,45 @@ internal class RedisSortedSetCoroutinesCommandsImpl(internal v override suspend fun zmscore(key: K, vararg members: V): List = ops.zmscore(key, *members).awaitFirstOrNull().orEmpty() - override suspend fun zpopmin(key: K): ScoredValue? = ops.zpopmin(key).awaitFirstOrNull() + override suspend fun zpopmin(key: K): ScoredValue? = + ops.zpopmin(key).awaitFirstOrNull() - override fun zpopmin(key: K, count: Long): Flow> = ops.zpopmin(key, count).asFlow() + override fun zpopmin(key: K, count: Long): Flow> = + ops.zpopmin(key, count).asFlow() - override suspend fun zpopmax(key: K): ScoredValue? = ops.zpopmax(key).awaitFirstOrNull() + override suspend fun zpopmax(key: K): ScoredValue? = + ops.zpopmax(key).awaitFirstOrNull() - override fun zpopmax(key: K, count: Long): Flow> = ops.zpopmax(key, count).asFlow() + override fun zpopmax(key: K, count: Long): Flow> = + ops.zpopmax(key, count).asFlow() - override fun zrange(key: K, start: Long, stop: Long): Flow = ops.zrange(key, start, stop).asFlow() + override suspend fun zrandmember(key: K): V? = ops.zrandmember(key).awaitFirstOrNull() - override fun zrangeWithScores(key: K, start: Long, stop: Long): Flow> = ops.zrangeWithScores(key, start, stop).asFlow() + override suspend fun zrandmember(key: K, count: Long): List = + ops.zrandmember(key, count).asFlow().toList() - override fun zrangebylex(key: K, range: Range): Flow = ops.zrangebylex(key, range).asFlow() + override suspend fun zrandmemberWithscores(key: K): ScoredValue? = + ops.zrandmemberWithscores(key).awaitFirstOrNull() - override fun zrangebylex(key: K, range: Range, limit: Limit): Flow = ops.zrangebylex(key, range, limit).asFlow() + override suspend fun zrandmemberWithscores( + key: K, + count: Long + ): List> = ops.zrandmemberWithscores(key, count).asFlow().toList() - override fun zrangebyscore(key: K, range: Range): Flow = ops.zrangebyscore(key, range).asFlow() + override fun zrange(key: K, start: Long, stop: Long): Flow = + ops.zrange(key, start, stop).asFlow() + + override fun zrangeWithScores(key: K, start: Long, stop: Long): Flow> = + ops.zrangeWithScores(key, start, stop).asFlow() + + override fun zrangebylex(key: K, range: Range): Flow = + ops.zrangebylex(key, range).asFlow() + + override fun zrangebylex(key: K, range: Range, limit: Limit): Flow = + ops.zrangebylex(key, range, limit).asFlow() + + override fun zrangebyscore(key: K, range: Range): Flow = + ops.zrangebyscore(key, range).asFlow() override fun zrangebyscore(key: K, range: Range, limit: Limit): Flow = ops.zrangebyscore(key, range, limit).asFlow() diff --git a/src/main/templates/io/lettuce/core/api/RedisHashCommands.java b/src/main/templates/io/lettuce/core/api/RedisHashCommands.java index 3ab274e2b1..204414fe83 100644 --- a/src/main/templates/io/lettuce/core/api/RedisHashCommands.java +++ b/src/main/templates/io/lettuce/core/api/RedisHashCommands.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.Map; -import io.lettuce.core.*; import io.lettuce.core.output.KeyStreamingChannel; import io.lettuce.core.output.KeyValueStreamingChannel; import io.lettuce.core.output.ValueStreamingChannel; @@ -151,11 +150,51 @@ public interface RedisHashCommands { * Set multiple hash fields to multiple values. * * @param key the key. - * @param map the null. + * @param map the hash to apply. * @return String simple-string-reply. */ String hmset(K key, Map map); + /** + * Return a random field from the hash stored at {@code key}. + * + * @param key the key. + * @return hash field name. + * @since 6.1 + */ + K hrandfield(K key); + + /** + * Return {@code count} random fields from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply list of field names. + * @since 6.1 + */ + List hrandfield(K key, long count); + + /** + * Return a random field along its value from the hash stored at {@code key}. + * + * @param key the key. + * @return array-reply the key and value. + * @since 6.1 + */ + KeyValue hrandfieldWithvalues(K key); + + /** + * Return {@code count} random fields along their value from the hash stored at {@code key}. + * + * @param key the key. + * @param count the number of fields to return. If the provided count argument is positive, return an array of distinct + * fields. + * @return array-reply the keys and values. + * @since 6.1 + */ + List> hrandfieldWithvalues(K key, long count); + /** * Incrementally iterate hash fields and associated values. * diff --git a/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java b/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java index 124c494a1c..a85a2f7859 100644 --- a/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java +++ b/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java @@ -363,6 +363,45 @@ public interface RedisSortedSetCommands { */ List> zpopmax(K key, long count); + /** + * Return a random member from the sorted set stored at {@code key}. + * + * @param key the key. + * @return element. + * @since 6.1 + */ + V zrandmember(K key); + + /** + * Return {@code count} random members from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + List zrandmember(K key, long count); + + /** + * Return a random member along its value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return the score and element. + * @since 6.1 + */ + ScoredValue zrandmemberWithscores(K key); + + /** + * Return {@code count} random members along their value from the sorted set stored at {@code key}. + * + * @param key the key. + * @param count the number of members to return. If the provided count argument is positive, return an array of distinct fields. + * @return List<ScoredValue<V>> array-reply list of scores and elements. + * @since 6.1 + */ + List> zrandmemberWithscores(K key, long count); + /** * Return a range of members in a sorted set, by index. * diff --git a/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java index 2482e4f8d2..8e1a65b0e8 100644 --- a/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/HashCommandIntegrationTests.java @@ -15,8 +15,7 @@ */ package io.lettuce.core.commands; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.offset; +import static org.assertj.core.api.Assertions.*; import java.util.Collections; import java.util.LinkedHashMap; @@ -30,7 +29,12 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; -import io.lettuce.core.*; +import io.lettuce.core.KeyValue; +import io.lettuce.core.MapScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.StreamScanCursor; +import io.lettuce.core.TestSupport; import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.test.KeyValueStreamingAdapter; import io.lettuce.test.LettuceExtension; @@ -220,6 +224,25 @@ void hmsetWithNulls() { assertThat(redis.hmget(key, "one")).isEqualTo(list(kv("one", ""))); } + @Test + @EnabledOnCommand("HRANDFIELD") + void hrandfield() { + + Map hash = new LinkedHashMap<>(); + hash.put("one", "1"); + hash.put("two", "2"); + hash.put("three", "3"); + + redis.hset(key, hash); + + assertThat(redis.hrandfield(key)).isIn("one", "two", "three"); + assertThat(redis.hrandfield(key, 2)).hasSize(2).containsAnyOf("one", "two", "three"); + assertThat(redis.hrandfieldWithvalues(key)).isIn(KeyValue.fromNullable("one", "1"), KeyValue.fromNullable("two", "2"), + KeyValue.fromNullable("three", "3")); + assertThat(redis.hrandfieldWithvalues(key, 2)).hasSize(2).containsAnyOf(KeyValue.fromNullable("one", "1"), + KeyValue.fromNullable("two", "2"), KeyValue.fromNullable("three", "3")); + } + @Test void hset() { assertThat(redis.hset(key, "one", "1")).isTrue(); diff --git a/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java index df327017b3..29d1a342ad 100644 --- a/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java @@ -304,6 +304,20 @@ void zpopmax() { assertThat(redis.zpopmax("foo")).isEqualTo(ScoredValue.empty()); } + @Test + @EnabledOnCommand("ZRANDMEMBER") + void zrandmember() { + + redis.zadd("zset", 2.0, "a", 3.0, "b", 4.0, "c"); + + assertThat(redis.zrandmember("zset")).isIn("a", "b", "c"); + assertThat(redis.zrandmember("zset", 2)).hasSize(2).containsAnyOf("a", "b", "c"); + assertThat(redis.zrandmemberWithscores("zset")).isIn(ScoredValue.fromNullable(2.0, "a"), + ScoredValue.fromNullable(3.0, "b"), ScoredValue.fromNullable(4.0, "c")); + assertThat(redis.zrandmemberWithscores("zset", 2)).hasSize(2).containsAnyOf(ScoredValue.fromNullable(2.0, "a"), + ScoredValue.fromNullable(3.0, "b"), ScoredValue.fromNullable(4.0, "c")); + } + @Test void zrange() { setup(); diff --git a/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java index 536d249ed4..2049b516bb 100644 --- a/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/StreamCommandIntegrationTests.java @@ -34,16 +34,7 @@ import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; -import io.lettuce.core.Consumer; -import io.lettuce.core.Limit; -import io.lettuce.core.Range; -import io.lettuce.core.StreamMessage; -import io.lettuce.core.TestSupport; -import io.lettuce.core.TransactionResult; -import io.lettuce.core.XAddArgs; -import io.lettuce.core.XClaimArgs; -import io.lettuce.core.XGroupCreateArgs; -import io.lettuce.core.XReadArgs; +import io.lettuce.core.*; import io.lettuce.core.XReadArgs.StreamOffset; import io.lettuce.core.api.sync.RedisCommands; import io.lettuce.core.codec.StringCodec;