Skip to content

Commit 111a7e2

Browse files
committed
Support ZINTERCARD
Resolves: #3253 Signed-off-by: heka1024 <heka1024@gmail.com>
1 parent 9787a5a commit 111a7e2

19 files changed

+466
-0
lines changed

src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,16 @@ public Long zInterStore(byte[] destKey, byte[]... sets) {
10841084
return convertAndReturn(delegate.zInterStore(destKey, sets), Converters.identityConverter());
10851085
}
10861086

1087+
@Override
1088+
public Long zInterCard(byte[]... sets) {
1089+
return convertAndReturn(delegate.zInterCard(sets), Converters.identityConverter());
1090+
}
1091+
1092+
@Override
1093+
public Long zInterCard(long limit, byte[]... sets) {
1094+
return convertAndReturn(delegate.zInterCard(limit, sets), Converters.identityConverter());
1095+
}
1096+
10871097
@Override
10881098
public Set<byte[]> zRange(byte[] key, long start, long end) {
10891099
return convertAndReturn(delegate.zRange(key, start, end), Converters.identityConverter());
@@ -2089,6 +2099,11 @@ public Long zInterStore(String destKey, String... sets) {
20892099
return zInterStore(serialize(destKey), serializeMulti(sets));
20902100
}
20912101

2102+
@Override
2103+
public Long zInterCard(String... keys) {
2104+
return zInterCard(serializeMulti(keys));
2105+
}
2106+
20922107
@Override
20932108
public byte[] zRandMember(byte[] key) {
20942109
return delegate.zRandMember(key);

src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,20 @@ default Long zInterStore(byte[] destKey, byte[]... sets) {
11461146
return zSetCommands().zInterStore(destKey, sets);
11471147
}
11481148

1149+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1150+
@Override
1151+
@Deprecated
1152+
default Long zInterCard(byte[]... sets) {
1153+
return zSetCommands().zInterCard(sets);
1154+
}
1155+
1156+
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
1157+
@Override
1158+
@Deprecated
1159+
default Long zInterCard(long limit, byte[]... sets) {
1160+
return zSetCommands().zInterCard(limit, sets);
1161+
}
1162+
11491163
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
11501164
@Override
11511165
@Deprecated

src/main/java/org/springframework/data/redis/connection/ReactiveZSetCommands.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,72 @@ default Mono<Long> zInterStore(ByteBuffer destinationKey, List<ByteBuffer> sets,
30263026
*/
30273027
Flux<NumericResponse<ZAggregateStoreCommand, Long>> zInterStore(Publisher<? extends ZAggregateStoreCommand> commands);
30283028

3029+
/**
3030+
* {@code ZINTERCARD} command parameters.
3031+
*
3032+
* @author GyeongHoe Koo
3033+
* @since 4.0
3034+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
3035+
*/
3036+
class ZInterCardCommand implements Command {
3037+
3038+
private final List<ByteBuffer> keys;
3039+
3040+
private ZInterCardCommand(List<ByteBuffer> keys) {
3041+
this.keys = keys;
3042+
}
3043+
3044+
/**
3045+
* Creates a new {@link ZInterCardCommand} given a {@link Collection} of keys.
3046+
*
3047+
* @param keys must not be {@literal null}.
3048+
* @return a new {@link ZInterCardCommand} for a {@link Collection} of keys.
3049+
*/
3050+
public static ZInterCardCommand keys(Collection<ByteBuffer> keys) {
3051+
3052+
Assert.notNull(keys, "Keys must not be null");
3053+
3054+
return new ZInterCardCommand(new ArrayList<>(keys));
3055+
}
3056+
3057+
@Override
3058+
public @Nullable ByteBuffer getKey() {
3059+
return null;
3060+
}
3061+
3062+
/**
3063+
* @return never {@literal null}.
3064+
*/
3065+
public List<ByteBuffer> getKeys() {
3066+
return keys;
3067+
}
3068+
}
3069+
3070+
/**
3071+
* Get the number of elements in the intersection of all given sorted sets.
3072+
*
3073+
* @param keys must not be {@literal null}.
3074+
* @return
3075+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
3076+
* @since 4.0
3077+
*/
3078+
default Mono<Long> zInterCard(List<ByteBuffer> keys) {
3079+
3080+
Assert.notNull(keys, "Keys must not be null");
3081+
3082+
return zInterCard(Mono.just(ZInterCardCommand.keys(keys))).next().map(NumericResponse::getOutput);
3083+
}
3084+
3085+
/**
3086+
* Get the number of elements in the intersection of all given sorted sets.
3087+
*
3088+
* @param commands must not be {@literal null}.
3089+
* @return
3090+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
3091+
* @since 4.0
3092+
*/
3093+
Flux<NumericResponse<ZInterCardCommand, Long>> zInterCard(Publisher<ZInterCardCommand> commands);
3094+
30293095
/**
30303096
* Union sorted {@literal sets}.
30313097
*

src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
* @author Mark Paluch
4343
* @author Andrey Shlykov
4444
* @author Shyngys Sapraliyev
45+
* @author GyeongHoe Koo
4546
* @see RedisCommands
4647
*/
4748
@NullUnmarked
@@ -1085,6 +1086,28 @@ default Long zInterStore(byte @NonNull [] destKey, @NonNull Aggregate aggregate,
10851086
Long zInterStore(byte @NonNull [] destKey, @NonNull Aggregate aggregate, @NonNull Weights weights,
10861087
byte @NonNull [] @NonNull... sets);
10871088

1089+
/**
1090+
* Get the number of members in the intersection of sorted {@code sets}.
1091+
*
1092+
* @param sets must not be {@literal null}.
1093+
* @return {@literal null} when used in pipeline / transaction.
1094+
* @since 4.0
1095+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
1096+
*/
1097+
Long zInterCard(byte @NonNull [] @NonNull... sets);
1098+
1099+
/**
1100+
* Get the number of members in the intersection of sorted {@code sets}.
1101+
*
1102+
* @param sets must not be {@literal null}.
1103+
* @param limit the maximum cardinality to compute. If the intersection has more than {@code limit} elements,
1104+
* the computation stops and returns {@code limit}.
1105+
* @return {@literal null} when used in pipeline / transaction.
1106+
* @since 4.0
1107+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
1108+
*/
1109+
Long zInterCard(long limit, byte @NonNull [] @NonNull... sets);
1110+
10881111
/**
10891112
* Union sorted {@code sets}.
10901113
*

src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,17 @@ Set<StringTuple> zInterWithScores(@NonNull Aggregate aggregate, @NonNull Weights
18371837
Long zInterStore(@NonNull String destKey, @NonNull Aggregate aggregate, int @NonNull [] weights,
18381838
@NonNull String @NonNull... sets);
18391839

1840+
/**
1841+
* Get the number of elements in the intersection of the sorted sets at the given {@code keys}.
1842+
*
1843+
* @param keys must not be {@literal null}.
1844+
* @return {@literal null} when used in pipeline / transaction.
1845+
* @since 4.0
1846+
* @see <a href="https://redis.io/commands/zintercard">Redis Documentation: ZINTERCARD</a>
1847+
* @see RedisZSetCommands#zInterCard(byte[]...)
1848+
*/
1849+
Long zInterCard(@NonNull String @NonNull... keys);
1850+
18401851
/**
18411852
* Union sorted {@code sets}.
18421853
*

src/main/java/org/springframework/data/redis/connection/jedis/JedisClusterZSetCommands.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,42 @@ public Long zUnionStore(byte @NonNull [] destKey, @NonNull Aggregate aggregate,
10861086
throw new InvalidDataAccessApiUsageException("ZUNIONSTORE can only be executed when all keys map to the same slot");
10871087
}
10881088

1089+
@Override
1090+
public Long zInterCard(byte @NonNull [] @NonNull... sets) {
1091+
1092+
Assert.notNull(sets, "Sets must not be null");
1093+
Assert.noNullElements(sets, "Sets must not contain null elements");
1094+
1095+
if (ClusterSlotHashUtil.isSameSlotForAllKeys(sets)) {
1096+
1097+
try {
1098+
return connection.getCluster().zintercard(sets);
1099+
} catch (Exception ex) {
1100+
throw convertJedisAccessException(ex);
1101+
}
1102+
}
1103+
1104+
throw new InvalidDataAccessApiUsageException("ZINTERCARD can only be executed when all keys map to the same slot");
1105+
}
1106+
1107+
@Override
1108+
public Long zInterCard(long limit, byte @NonNull [] @NonNull... sets) {
1109+
1110+
Assert.notNull(sets, "Sets must not be null");
1111+
Assert.noNullElements(sets, "Sets must not contain null elements");
1112+
1113+
if (ClusterSlotHashUtil.isSameSlotForAllKeys(sets)) {
1114+
1115+
try {
1116+
return connection.getCluster().zintercard(limit, sets);
1117+
} catch (Exception ex) {
1118+
throw convertJedisAccessException(ex);
1119+
}
1120+
}
1121+
1122+
throw new InvalidDataAccessApiUsageException("ZINTERCARD can only be executed when all keys map to the same slot");
1123+
}
1124+
10891125
@Override
10901126
public Cursor<@NonNull Tuple> zScan(byte @NonNull [] key, @NonNull ScanOptions options) {
10911127

src/main/java/org/springframework/data/redis/connection/jedis/JedisZSetCommands.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,24 @@ public Long zUnionStore(byte @NonNull [] destKey, byte @NonNull [] @NonNull... s
564564
return connection.invoke().just(Jedis::zunionstore, PipelineBinaryCommands::zunionstore, destKey, sets);
565565
}
566566

567+
@Override
568+
public Long zInterCard(byte @NonNull [] @NonNull... sets) {
569+
570+
Assert.notNull(sets, "Sets must not be null");
571+
Assert.noNullElements(sets, "Sets must not contain null elements");
572+
573+
return connection.invoke().just(Jedis::zintercard, PipelineBinaryCommands::zintercard, sets);
574+
}
575+
576+
@Override
577+
public Long zInterCard(long limit, byte @NonNull [] @NonNull... sets) {
578+
579+
Assert.notNull(sets, "Sets must not be null");
580+
Assert.noNullElements(sets, "Sets must not contain null elements");
581+
582+
return connection.invoke().just(Jedis::zintercard, PipelineBinaryCommands::zintercard, limit, sets);
583+
}
584+
567585
@Override
568586
public Cursor<@NonNull Tuple> zScan(byte @NonNull [] key, @NonNull ScanOptions options) {
569587
return zScan(key, CursorId.initial(), options);

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveZSetCommands.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,19 @@ public Flux<NumericResponse<ZAggregateStoreCommand, Long>> zInterStore(
624624
}));
625625
}
626626

627+
@Override
628+
public Flux<NumericResponse<ZInterCardCommand, Long>> zInterCard(Publisher<ZInterCardCommand> commands) {
629+
630+
return this.connection.execute(reactiveCommands -> Flux.from(commands).concatMap(command -> {
631+
632+
Assert.notEmpty(command.getKeys(), "Keys must not be null or empty");
633+
634+
ByteBuffer[] keys = command.getKeys().toArray(new ByteBuffer[0]);
635+
636+
return reactiveCommands.zintercard(keys).map(value -> new NumericResponse<>(command, value));
637+
}));
638+
}
639+
627640
@Override
628641
public Flux<CommandResponse<ZAggregateCommand, Flux<ByteBuffer>>> zUnion(
629642
Publisher<? extends ZAggregateCommand> commands) {

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceZSetCommands.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,24 @@ public Long zUnionStore(byte @NonNull [] destKey, byte @NonNull [] @NonNull... s
532532
return connection.invoke().just(RedisSortedSetAsyncCommands::zunionstore, destKey, sets);
533533
}
534534

535+
@Override
536+
public Long zInterCard(byte @NonNull [] @NonNull... sets) {
537+
538+
Assert.notNull(sets, "Sets must not be null");
539+
Assert.noNullElements(sets, "Sets must not contain null elements");
540+
541+
return connection.invoke().just(RedisSortedSetAsyncCommands::zintercard, sets);
542+
}
543+
544+
@Override
545+
public Long zInterCard(long limit, byte @NonNull [] @NonNull... sets) {
546+
547+
Assert.notNull(sets, "Sets must not be null");
548+
Assert.noNullElements(sets, "Sets must not contain null elements");
549+
550+
return connection.invoke().just(RedisSortedSetAsyncCommands::zintercard, limit, sets);
551+
}
552+
535553
@Override
536554
public Cursor<@NonNull Tuple> zScan(byte @NonNull [] key, @Nullable ScanOptions options) {
537555
return zScan(key, CursorId.initial(), options != null ? options : ScanOptions.NONE);

src/main/java/org/springframework/data/redis/core/DefaultReactiveZSetOperations.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,18 @@ public Mono<Long> intersectAndStore(K key, Collection<K> otherKeys, K destKey, A
585585
.flatMap(serialized -> zSetCommands.zInterStore(rawKey(destKey), serialized, weights, aggregate)));
586586
}
587587

588+
@Override
589+
public Mono<Long> intersectSize(K key, Collection<K> otherKeys) {
590+
591+
Assert.notNull(key, "Key must not be null");
592+
Assert.notNull(otherKeys, "Other keys must not be null");
593+
594+
return createMono(zSetCommands -> Flux.fromIterable(getKeys(key, otherKeys)) //
595+
.map(this::rawKey) //
596+
.collectList() //
597+
.flatMap(zSetCommands::zInterCard));
598+
}
599+
588600
@Override
589601
public Flux<V> union(K key, Collection<K> otherKeys) {
590602

0 commit comments

Comments
 (0)