From 851d5c7f51ab7be9624df15ee2ba5e539dd62d65 Mon Sep 17 00:00:00 2001 From: dengliming Date: Thu, 14 Jan 2021 00:41:11 +0800 Subject: [PATCH] Add support for ZDIFF and ZDIFFSTORE commands #1507 Original pull request: #1587. --- .../core/AbstractRedisAsyncCommands.java | 15 +++++++++ .../core/AbstractRedisReactiveCommands.java | 15 +++++++++ .../io/lettuce/core/RedisCommandBuilder.java | 26 +++++++++++++++ .../async/RedisSortedSetAsyncCommands.java | 28 ++++++++++++++++ .../RedisSortedSetReactiveCommands.java | 28 ++++++++++++++++ .../core/api/sync/RedisSortedSetCommands.java | 28 ++++++++++++++++ .../NodeSelectionSortedSetAsyncCommands.java | 28 ++++++++++++++++ .../sync/NodeSelectionSortedSetCommands.java | 28 ++++++++++++++++ .../io/lettuce/core/protocol/CommandType.java | 2 +- .../RedisSortedSetCoroutinesCommands.kt | 28 ++++++++++++++++ .../RedisSortedSetCoroutinesCommandsImpl.kt | 6 ++++ .../core/api/RedisSortedSetCommands.java | 28 ++++++++++++++++ .../KotlinCompilationUnitFactory.java | 2 +- .../SortedSetCommandIntegrationTests.java | 32 +++++++++++++++++++ 14 files changed, 292 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index 4e32ca24b6..ca2f13e388 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -1832,6 +1832,21 @@ public RedisFuture zcount(K key, Range range) { return dispatch(commandBuilder.zcount(key, range)); } + @Override + public RedisFuture> zdiff(K... keys) { + return dispatch(commandBuilder.zdiff(keys)); + } + + @Override + public RedisFuture zdiffstore(K destKey, K... srcKeys) { + return dispatch(commandBuilder.zdiffstore(destKey, srcKeys)); + } + + @Override + public RedisFuture>> zdiffWithScores(K... keys) { + return dispatch(commandBuilder.zdiffWithScores(keys)); + } + @Override public RedisFuture zincrby(K key, double amount, V member) { return dispatch(commandBuilder.zincrby(key, amount, member)); diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index ee53d566fb..e7245fc285 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -1907,6 +1907,21 @@ public Mono zcount(K key, Range range) { return createMono(() -> commandBuilder.zcount(key, range)); } + @Override + public Flux zdiff(K... keys) { + return createDissolvingFlux(() -> commandBuilder.zdiff(keys)); + } + + @Override + public Mono zdiffstore(K destKey, K... srcKeys) { + return createMono(() -> commandBuilder.zdiffstore(destKey, srcKeys)); + } + + @Override + public Flux> zdiffWithScores(K... keys) { + return createDissolvingFlux(() -> commandBuilder.zdiffWithScores(keys)); + } + @Override public Mono zincrby(K key, double amount, V member) { return createMono(() -> commandBuilder.zincrby(key, amount, member)); diff --git a/src/main/java/io/lettuce/core/RedisCommandBuilder.java b/src/main/java/io/lettuce/core/RedisCommandBuilder.java index 3703011b99..5f024fe844 100644 --- a/src/main/java/io/lettuce/core/RedisCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RedisCommandBuilder.java @@ -2674,6 +2674,32 @@ Command zcount(K key, Range range) { return createCommand(ZCOUNT, new IntegerOutput<>(codec), args); } + Command > zdiff(K... keys) { + notEmpty(keys); + + CommandArgs args = new CommandArgs<>(codec); + args.add(keys.length).addKeys(keys); + System.out.println(args); + return createCommand(ZDIFF, new ValueListOutput<>(codec), args); + } + + Command zdiffstore(K destKey, K... srcKeys) { + notNullKey(destKey); + notEmpty(srcKeys); + + CommandArgs args = new CommandArgs<>(codec); + args.addKey(destKey).add(srcKeys.length).addKeys(srcKeys); + return createCommand(ZDIFFSTORE, new IntegerOutput<>(codec), args); + } + + Command>> zdiffWithScores(K... keys) { + notEmpty(keys); + + CommandArgs args = new CommandArgs<>(codec); + args.add(keys.length).addKeys(keys).add(WITHSCORES); + return createCommand(ZDIFF, new ScoredValueListOutput<>(codec), args); + } + Command zincrby(K key, double amount, V member) { notNullKey(key); 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 68c3af3308..54296c4774 100644 --- a/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RedisSortedSetAsyncCommands.java @@ -198,6 +198,34 @@ public interface RedisSortedSetAsyncCommands { */ RedisFuture zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of elements. + * @since 6.2 + */ + RedisFuture> zdiff(K... keys); + + /** + * 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.2 + */ + RedisFuture zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of scored values. + * @since 6.2 + */ + RedisFuture>> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * 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 6aa2cc1ac0..40c1ffbd3e 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RedisSortedSetReactiveCommands.java @@ -200,6 +200,34 @@ public interface RedisSortedSetReactiveCommands { */ Mono zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return V array-reply list of elements. + * @since 6.2 + */ + Flux zdiff(K... keys); + + /** + * 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.2 + */ + Mono zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return V array-reply list of scored values. + * @since 6.2 + */ + Flux> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * 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 8ea352d8cf..d6fcf2e08b 100644 --- a/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RedisSortedSetCommands.java @@ -198,6 +198,34 @@ public interface RedisSortedSetCommands { */ Long zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of elements. + * @since 6.2 + */ + List zdiff(K... keys); + + /** + * 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.2 + */ + Long zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of scored values. + * @since 6.2 + */ + List> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * 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 8ce71ccde4..d3137faace 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 @@ -198,6 +198,34 @@ public interface NodeSelectionSortedSetAsyncCommands { */ AsyncExecutions zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of elements. + * @since 6.2 + */ + AsyncExecutions> zdiff(K... keys); + + /** + * 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.2 + */ + AsyncExecutions zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of scored values. + * @since 6.2 + */ + AsyncExecutions>> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * 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 3c13f30454..00d404d013 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 @@ -198,6 +198,34 @@ public interface NodeSelectionSortedSetCommands { */ Executions zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of elements. + * @since 6.2 + */ + Executions> zdiff(K... keys); + + /** + * 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.2 + */ + Executions zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of scored values. + * @since 6.2 + */ + Executions>> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * diff --git a/src/main/java/io/lettuce/core/protocol/CommandType.java b/src/main/java/io/lettuce/core/protocol/CommandType.java index c9a7046522..50ea48aada 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandType.java +++ b/src/main/java/io/lettuce/core/protocol/CommandType.java @@ -78,7 +78,7 @@ public enum CommandType implements ProtocolKeyword { // Sorted Set - BZPOPMIN, BZPOPMAX, ZADD, ZCARD, ZCOUNT, 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, 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/RedisSortedSetCoroutinesCommands.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt index 8ff6ab6e8e..d7488556e4 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommands.kt @@ -173,6 +173,34 @@ interface RedisSortedSetCoroutinesCommands { */ suspend fun zcount(key: K, range: Range): Long? + /** + * 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.2 + */ + 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.2 + */ + 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.2 + */ + fun zdiffWithScores(vararg keys: K): Flow> + /** * Increment the score of a member in a sorted set. * 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 ba1368a30a..0a2f1a6079 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RedisSortedSetCoroutinesCommandsImpl.kt @@ -60,6 +60,12 @@ internal class RedisSortedSetCoroutinesCommandsImpl(internal v override suspend fun zcount(key: K, range: Range): Long? = ops.zcount(key, range).awaitFirstOrNull() + override fun zdiff(vararg keys: K): Flow = ops.zdiff(*keys).asFlow() + + override suspend fun zdiffstore(destKey: K, vararg srcKeys: K): Long? = ops.zdiffstore(destKey, *srcKeys).awaitFirstOrNull() + + override fun zdiffWithScores(vararg keys: K): Flow> = ops.zdiffWithScores(*keys).asFlow() + override suspend fun zincrby(key: K, amount: Double, member: V): Double? = ops.zincrby(key, amount, member).awaitFirstOrNull() override fun zinter(vararg keys: K): Flow = ops.zinter(*keys).asFlow() diff --git a/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java b/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java index 1b9b289885..51bcf55b76 100644 --- a/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java +++ b/src/main/templates/io/lettuce/core/api/RedisSortedSetCommands.java @@ -197,6 +197,34 @@ public interface RedisSortedSetCommands { */ Long zcount(K key, Range range); + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of elements. + * @since 6.2 + */ + List zdiff(K... keys); + + /** + * 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.2 + */ + Long zdiffstore(K destKey, K... srcKeys); + + /** + * Computes the difference between the first and all successive input sorted sets. + * + * @param keys the keys. + * @return List<V> array-reply list of scored values. + * @since 6.2 + */ + List> zdiffWithScores(K... keys); + /** * Increment the score of a member in a sorted set. * diff --git a/src/test/java/io/lettuce/apigenerator/KotlinCompilationUnitFactory.java b/src/test/java/io/lettuce/apigenerator/KotlinCompilationUnitFactory.java index 559350ace3..eb895dcb48 100644 --- a/src/test/java/io/lettuce/apigenerator/KotlinCompilationUnitFactory.java +++ b/src/test/java/io/lettuce/apigenerator/KotlinCompilationUnitFactory.java @@ -61,7 +61,7 @@ class KotlinCompilationUnitFactory { private static final Set SKIP_METHODS = LettuceSets.unmodifiableSet("BaseRedisCommands.reset", "getStatefulConnection"); private static final Set FLOW_METHODS = LettuceSets.unmodifiableSet("dispatch", "geohash", "georadius", "georadiusbymember", "hgetall", "hkeys", "hmget", "hvals", "keys", "mget", "sdiff", "sinter", "smembers", "smismember", "sort", "srandmember", "sunion", - "xclaim", "xpending", "xrange", "xread", "xreadgroup", "xrevrange", "zinter", "zinterWithScores", "zpopmax", "zpopmin", "zrange", + "xclaim", "xpending", "xrange", "xread", "xreadgroup", "xrevrange", "zdiff", "zdiffWithScores", "zinter", "zinterWithScores", "zpopmax", "zpopmin", "zrange", "zrangeWithScores", "zrangebylex", "zrangebyscore", "zrangebyscoreWithScores", "zrevrange", "zrevrangeWithScores", "zrevrangebylex", "zrevrangebyscore", "zrevrangebyscore", "zrevrangebyscoreWithScores", "zunion", "zunionWithScores"); diff --git a/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java index 6945e6411c..df327017b3 100644 --- a/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/SortedSetCommandIntegrationTests.java @@ -212,6 +212,38 @@ void zcount() { assertThat(redis.zcount(key, Range.unbounded())).isEqualTo(3); } + @Test + @EnabledOnCommand("ZDIFF") // Redis 6.2 + void zdiff() { + String zset1 = "zset1"; + String zset2 = "zset2"; + + assertThat(redis.zadd(zset1, 1.0, "one")).isEqualTo(1); + assertThat(redis.zadd(zset1, 2.0, "two")).isEqualTo(1); + assertThat(redis.zadd(zset1, 3.0, "three")).isEqualTo(1); + assertThat(redis.zadd(zset2, 1.0, "one")).isEqualTo(1); + assertThat(redis.zadd(zset2, 2.0, "two")).isEqualTo(1); + + assertThat(redis.zdiff(zset1, zset2)).isEqualTo(list("three")); + assertThat(redis.zdiffWithScores(zset1, zset2)).isEqualTo(svlist(sv(3.0, "three"))); + } + + @Test + @EnabledOnCommand("ZDIFFSTORE") // Redis 6.2 + void zdiffstore() { + String zset1 = "zset1"; + String zset2 = "zset2"; + + assertThat(redis.zadd(zset1, 1.0, "one")).isEqualTo(1); + assertThat(redis.zadd(zset1, 2.0, "two")).isEqualTo(1); + assertThat(redis.zadd(zset1, 3.0, "three")).isEqualTo(1); + assertThat(redis.zadd(zset2, 1.0, "one")).isEqualTo(1); + assertThat(redis.zadd(zset2, 2.0, "two")).isEqualTo(1); + + assertThat(redis.zdiffstore("out", zset1, zset2)).isEqualTo(1); + assertThat(redis.zrangeWithScores("out", 0, -1)).isEqualTo(svlist(sv(3.0, "three"))); + } + @Test void zincrby() { assertThat(redis.zincrby(key, 0.0, "a")).isEqualTo(0, offset(0.1));