Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
* @author Dennis Neufeld
* @author Shyngys Sapraliyev
* @author Jeonggyu Choi
* @author Mingi Lee
*/
@NullUnmarked
@SuppressWarnings({ "ConstantConditions", "deprecation" })
Expand Down Expand Up @@ -832,6 +833,11 @@ public Long sInterStore(byte[] destKey, byte[]... keys) {
return convertAndReturn(delegate.sInterStore(destKey, keys), Converters.identityConverter());
}

@Override
public Long sInterCard(byte[]... keys) {
return convertAndReturn(delegate.sInterCard(keys), Converters.identityConverter());
}

@Override
public Boolean sIsMember(byte[] key, byte[] value) {
return convertAndReturn(delegate.sIsMember(key, value), Converters.identityConverter());
Expand Down Expand Up @@ -1824,6 +1830,11 @@ public Long sInterStore(String destKey, String... keys) {
return sInterStore(serialize(destKey), serializeMulti(keys));
}

@Override
public Long sInterCard(String... keys) {
return sInterCard(serializeMulti(keys));
}

@Override
public Boolean sIsMember(String key, String value) {
return sIsMember(serialize(key), serialize(value));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
* @author Dennis Neufeld
* @author Shyngys Sapraliyev
* @author Tihomir Mateev
* @author Mingi Lee
* @since 2.0
*/
@Deprecated
Expand Down Expand Up @@ -890,6 +891,13 @@ default Long sInterStore(byte[] destKey, byte[]... keys) {
return setCommands().sInterStore(destKey, keys);
}

/** @deprecated in favor of {@link RedisConnection#setCommands()}}. */
@Override
@Deprecated
default Long sInterCard(byte[]... keys) {
return setCommands().sInterCard(keys);
}

/** @deprecated in favor of {@link RedisConnection#setCommands()}}. */
@Override
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* @author Costin Leau
* @author Christoph Strobl
* @author Mark Paluch
* @author Mingi Lee
* @see RedisCommands
*/
@NullUnmarked
Expand Down Expand Up @@ -153,6 +154,16 @@ public interface RedisSetCommands {
*/
Long sInterStore(byte @NonNull [] destKey, byte @NonNull [] @NonNull... keys);

/**
* Returns the cardinality of the set which would result from the intersection of all the given sets.
*
* @param keys must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/sintercard">Redis Documentation: SINTERCARD</a>
* @since 3.4
*/
Long sInterCard(byte @NonNull [] @NonNull... keys);

/**
* Union all sets at given {@code keys}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
* @author ihaohong
* @author Shyngys Sapraliyev
* @author Jeonggyu Choi
* @author Mingi Lee
* @see RedisCallback
* @see RedisSerializer
* @see StringRedisTemplate
Expand Down Expand Up @@ -1169,6 +1170,17 @@ String bLMove(@NonNull String sourceKey, @NonNull String destinationKey, @NonNul
*/
Long sInterStore(@NonNull String destKey, @NonNull String @NonNull... keys);

/**
* Returns the cardinality of the set which would result from the intersection of all the given sets.
*
* @param keys must not be {@literal null}.
* @return
* @see <a href="https://redis.io/commands/sintercard">Redis Documentation: SINTERCARD</a>
* @see RedisSetCommands#sInterCard(byte[]...)
* @since 3.4
*/
Long sInterCard(@NonNull String @NonNull... keys);

/**
* Union all sets at given {@code keys}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Mingi Lee
* @since 2.0
*/
class JedisClusterSetCommands implements RedisSetCommands {
Expand Down Expand Up @@ -230,6 +231,25 @@ public Long sInterStore(byte[] destKey, byte[]... keys) {
return sAdd(destKey, result.toArray(new byte[result.size()][]));
}

@Override
public Long sInterCard(byte[]... keys) {

Assert.notNull(keys, "Keys must not be null");
Assert.noNullElements(keys, "Keys must not contain null elements");

if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
try {
return connection.getCluster().sintercard(keys);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}

// For multi-slot clusters, calculate intersection cardinality by performing intersection
Set<byte[]> result = sInter(keys);
return (long) result.size();
}

@Override
public Set<byte[]> sUnion(byte[]... keys) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Mingi Lee
* @since 2.0
*/
@NullUnmarked
Expand Down Expand Up @@ -105,6 +106,15 @@ public Long sInterStore(byte @NonNull [] destKey, byte @NonNull [] @NonNull... k
return connection.invoke().just(Jedis::sinterstore, PipelineBinaryCommands::sinterstore, destKey, keys);
}

@Override
public Long sInterCard(byte @NonNull [] @NonNull... keys) {

Assert.notNull(keys, "Keys must not be null");
Assert.noNullElements(keys, "Keys must not contain null elements");

return connection.invoke().just(Jedis::sintercard, PipelineBinaryCommands::sintercard, keys);
}

@Override
public Boolean sIsMember(byte @NonNull [] key, byte @NonNull [] value) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Mingi Lee
* @since 2.0
*/
class LettuceClusterSetCommands extends LettuceSetCommands {
Expand Down Expand Up @@ -118,6 +119,21 @@ public Long sInterStore(byte[] destKey, byte[]... keys) {
return sAdd(destKey, result.toArray(new byte[result.size()][]));
}

@Override
public Long sInterCard(byte[]... keys) {

Assert.notNull(keys, "Keys must not be null");
Assert.noNullElements(keys, "Keys must not contain null elements");

if (ClusterSlotHashUtil.isSameSlotForAllKeys(keys)) {
return super.sInterCard(keys);
}

// For multi-slot clusters, calculate intersection cardinality by performing intersection
Set<byte[]> result = sInter(keys);
return (long) result.size();
}

@Override
public Set<byte[]> sUnion(byte[]... keys) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
/**
* @author Christoph Strobl
* @author Mark Paluch
* @author Mingi Lee
* @since 2.0
*/
@NullUnmarked
Expand Down Expand Up @@ -106,6 +107,15 @@ public Long sInterStore(byte @NonNull [] destKey, byte @NonNull [] @NonNull... k
return connection.invoke().just(RedisSetAsyncCommands::sinterstore, destKey, keys);
}

@Override
public Long sInterCard(byte @NonNull [] @NonNull... keys) {

Assert.notNull(keys, "Keys must not be null");
Assert.noNullElements(keys, "Keys must not contain null elements");

return connection.invoke().just(RedisSetAsyncCommands::sintercard, keys);
}

@Override
public Boolean sIsMember(byte @NonNull [] key, byte @NonNull [] value) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,25 @@ public Long intersectAndStore(Collection<K> keys, K destKey) {
return execute(connection -> connection.sInterStore(rawDestKey, rawKeys));
}

@Override
public Long intersectSize(K key, K otherKey) {
return intersectSize(Arrays.asList(key, otherKey));
}

@Override
public Long intersectSize(K key, Collection<K> otherKeys) {

byte[][] rawKeys = rawKeys(key, otherKeys);
return execute(connection -> connection.sInterCard(rawKeys));
}

@Override
public Long intersectSize(Collection<K> keys) {

byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.sInterCard(rawKeys));
}

@Override
public Boolean isMember(K key, Object o) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
* @author Christoph Strobl
* @author Mark Paluch
* @author Roman Bezpalko
* @author Mingi Lee
*/
@NullUnmarked
public interface SetOperations<K, V> {
Expand Down Expand Up @@ -178,6 +179,38 @@ public interface SetOperations<K, V> {
*/
Long intersectAndStore(@NonNull Collection<@NonNull K> keys, @NonNull K destKey);

/**
* Returns the cardinality of the set which would result from the intersection of {@code key} and {@code otherKey}.
*
* @param key must not be {@literal null}.
* @param otherKey must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/sintercard">Redis Documentation: SINTERCARD</a>
* @since 3.4
*/
Long intersectSize(@NonNull K key, @NonNull K otherKey);

/**
* Returns the cardinality of the set which would result from the intersection of {@code key} and {@code otherKeys}.
*
* @param key must not be {@literal null}.
* @param otherKeys must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/sintercard">Redis Documentation: SINTERCARD</a>
* @since 3.4
*/
Long intersectSize(@NonNull K key, @NonNull Collection<@NonNull K> otherKeys);

/**
* Returns the cardinality of the set which would result from the intersection of all given sets at {@code keys}.
*
* @param keys must not be {@literal null}.
* @return {@literal null} when used in pipeline / transaction.
* @see <a href="https://redis.io/commands/sintercard">Redis Documentation: SINTERCARD</a>
* @since 3.4
*/
Long intersectSize(@NonNull Collection<@NonNull K> keys);

/**
* Union all sets at given {@code keys} and {@code otherKey}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* @author Christoph Strobl
* @author Thomas Darimont
* @author Mark Paluch
* @author Mingi Lee
*/
@ParameterizedClass
@MethodSource("testParams")
Expand Down Expand Up @@ -329,6 +330,38 @@ void intersectAndStoreShouldReturnNumberOfElementsInDestination() {
assertThat(setOps.intersectAndStore(Arrays.asList(sourceKey1, sourceKey2), destinationKey)).isEqualTo(2L);
}

@Test // GH-2906
@EnabledOnCommand("SINTERCARD")
void intersectSizeShouldReturnIntersectionCardinality() {

K sourceKey1 = keyFactory.instance();
K sourceKey2 = keyFactory.instance();
K sourceKey3 = keyFactory.instance();

V v1 = valueFactory.instance();
V v2 = valueFactory.instance();
V v3 = valueFactory.instance();
V v4 = valueFactory.instance();
V v5 = valueFactory.instance();

setOps.add(sourceKey1, v1, v2, v3);
setOps.add(sourceKey2, v2, v3, v4);
setOps.add(sourceKey3, v3, v4, v5);

// Test two keys intersection
assertThat(setOps.intersectSize(sourceKey1, sourceKey2)).isEqualTo(2L);

// Test key and collection intersection
assertThat(setOps.intersectSize(sourceKey1, Arrays.asList(sourceKey2, sourceKey3))).isEqualTo(1L);

// Test collection intersection
assertThat(setOps.intersectSize(Arrays.asList(sourceKey1, sourceKey2, sourceKey3))).isEqualTo(1L);

// Test empty intersection
K emptyKey = keyFactory.instance();
assertThat(setOps.intersectSize(sourceKey1, emptyKey)).isEqualTo(0L);
}

@Test // GH-2037
@EnabledOnCommand("SMISMEMBER")
void isMember() {
Expand Down