Skip to content

Commit

Permalink
Java: Add Zinterstore command.
Browse files Browse the repository at this point in the history
  • Loading branch information
SanHalacogluImproving committed Apr 15, 2024
1 parent 5dec1ea commit d1eb85b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,6 @@ CompletableFuture<Map<String, Double>> zrangeWithScores(
* Stores a specified range of elements from the sorted set at <code>source</code>, into a new
* sorted set at <code>destination</code>. If <code>destination</code> doesn't exist, a new sorted
* set is created; if it exists, it's overwritten.<br>
* <code>ZRANGESTORE</code> can perform different types of range queries: by index (rank), by the
* score, or by lexicographical order.<br>
*
* @see <a href="https://redis.io/commands/zrangestore/">redis.io</a> for more details.
* @param destination The key for the destination sorted set.
Expand All @@ -442,7 +440,7 @@ CompletableFuture<Map<String, Double>> zrangeWithScores(
* @example
* <pre>{@code
* RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
* Long payload1 = client.zrange("destinationKey", "mySortedSet", query1, true).get();
* Long payload1 = client.zrangestore("destinationKey", "mySortedSet", query1, true).get();
* assert payload1 == 7L;
*
* RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
Expand All @@ -457,8 +455,6 @@ CompletableFuture<Long> zrangestore(
* Stores a specified range of elements from the sorted set at <code>source</code>, into a new
* sorted set at <code>destination</code>. If <code>destination</code> doesn't exist, a new sorted
* set is created; if it exists, it's overwritten.<br>
* <code>ZRANGESTORE</code> can perform different types of range queries: by index (rank), by the
* score, or by lexicographical order.<br>
*
* @see <a href="https://redis.io/commands/zrangestore/">redis.io</a> for more details.
* @param destination The key for the destination sorted set.
Expand All @@ -474,7 +470,7 @@ CompletableFuture<Long> zrangestore(
* @example
* <pre>{@code
* RangeByIndex query1 = new RangeByIndex(0, -1); // Query for all members.
* Long payload1 = client.zrange("destinationKey", "mySortedSet", query1).get();
* Long payload1 = client.zrangestore("destinationKey", "mySortedSet", query1).get();
* assert payload1 == 7L;
*
* RangeByScore query2 = new RangeByScore(InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3)); // Query for members with scores within the range of negative infinity to 3.
Expand Down
48 changes: 24 additions & 24 deletions java/client/src/main/java/glide/api/models/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -1512,30 +1512,6 @@ public T zrankWithScore(@NonNull String key, @NonNull String member) {
return getThis();
}

/**
* Stores a specified range of elements from the sorted set at <code>source</code>, into a new
* sorted set at <code>destination</code>. If <code>destination</code> doesn't exist, a new sorted
* set is created; if it exists, it's overwritten.<br>
* <code>ZRANGESTORE</code> can perform different types of range queries: by index (rank), by the
* score, or by lexicographical order.<br>
*
* @see <a href="https://redis.io/commands/zrangestore/">redis.io</a> for more details.
* @param destination The key for the destination sorted set.
* @param source The key of the source sorted set.
* @param rangeQuery The range query object representing the type of range query to perform.<br>
* <ul>
* <li>For range queries by index (rank), use {@link RangeByIndex}.
* <li>For range queries by lexicographical order, use {@link RangeByLex}.
* <li>For range queries by score, use {@link RangeByScore}.
* </ul>
*
* @return Command Response - The number of elements in the resulting sorted set.
*/
public T zrangestore(
@NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) {
return getThis().zrangestore(destination, source, rangeQuery, false);
}

/**
* Returns the scores associated with the specified <code>members</code> in the sorted set stored
* at <code>key</code>.
Expand Down Expand Up @@ -1684,6 +1660,30 @@ public T zrangestore(
return getThis();
}

/**
* Stores a specified range of elements from the sorted set at <code>source</code>, into a new
* sorted set at <code>destination</code>. If <code>destination</code> doesn't exist, a new sorted
* set is created; if it exists, it's overwritten.<br>
* <code>ZRANGESTORE</code> can perform different types of range queries: by index (rank), by the
* score, or by lexicographical order.<br>
*
* @see <a href="https://redis.io/commands/zrangestore/">redis.io</a> for more details.
* @param destination The key for the destination sorted set.
* @param source The key of the source sorted set.
* @param rangeQuery The range query object representing the type of range query to perform.<br>
* <ul>
* <li>For range queries by index (rank), use {@link RangeByIndex}.
* <li>For range queries by lexicographical order, use {@link RangeByLex}.
* <li>For range queries by score, use {@link RangeByScore}.
* </ul>
*
* @return Command Response - The number of elements in the resulting sorted set.
*/
public T zrangestore(
@NonNull String destination, @NonNull String source, @NonNull RangeQuery rangeQuery) {
return getThis().zrangestore(destination, source, rangeQuery, false);
}

/**
* Removes all elements in the sorted set stored at <code>key</code> with a lexicographical order
* between <code>minLex</code> and <code>maxLex</code>.
Expand Down
34 changes: 17 additions & 17 deletions java/client/src/test/java/glide/api/RedisClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2511,25 +2511,22 @@ public void zremrangebylex_returns_success() {

@SneakyThrows
@Test
public void zrangestore_by_lex_returns_success() {
public void zremrangebyscore_returns_success() {
// setup
String source = "testSourceKey";
String destination = "testDestinationKey";
RangeByLex rangeByLex =
new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false));
String[] arguments =
new String[] {source, destination, rangeByLex.getStart(), rangeByLex.getEnd(), "BYLEX"};
Long value = 2L;
String key = "testKey";
String[] arguments = new String[] {key, "-inf", "10.0"};
Long value = 3L;

CompletableFuture<Long> testResponse = new CompletableFuture<>();
testResponse.complete(value);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(ZRangeStore), eq(arguments), any()))
when(commandManager.<Long>submitNewCommand(eq(ZRemRangeByScore), eq(arguments), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response = service.zrangestore(source, destination, rangeByLex);
CompletableFuture<Long> response =
service.zremrangebyscore(key, InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(10, true));
Long payload = response.get();

// verify
Expand All @@ -2539,22 +2536,25 @@ public void zrangestore_by_lex_returns_success() {

@SneakyThrows
@Test
public void zremrangebyscore_returns_success() {
public void zrangestore_by_lex_returns_success() {
// setup
String key = "testKey";
String[] arguments = new String[] {key, "-inf", "10.0"};
Long value = 3L;
String source = "testSourceKey";
String destination = "testDestinationKey";
RangeByLex rangeByLex =
new RangeByLex(InfLexBound.NEGATIVE_INFINITY, new LexBoundary("c", false));
String[] arguments =
new String[] {source, destination, rangeByLex.getStart(), rangeByLex.getEnd(), "BYLEX"};
Long value = 2L;

CompletableFuture<Long> testResponse = new CompletableFuture<>();
testResponse.complete(value);

// match on protobuf request
when(commandManager.<Long>submitNewCommand(eq(ZRemRangeByScore), eq(arguments), any()))
when(commandManager.<Long>submitNewCommand(eq(ZRangeStore), eq(arguments), any()))
.thenReturn(testResponse);

// exercise
CompletableFuture<Long> response =
service.zremrangebyscore(key, InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(10, true));
CompletableFuture<Long> response = service.zrangestore(source, destination, rangeByLex);
Long payload = response.get();

// verify
Expand Down
78 changes: 39 additions & 39 deletions java/integTest/src/test/java/glide/SharedCommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -1566,45 +1566,6 @@ public void zremrangebylex(BaseClient client) {
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void zrangestore_by_index(BaseClient client) {
String key = "{testKey}:" + UUID.randomUUID();
String destination = "{testKey}:" + UUID.randomUUID();
String source = "{testKey}:" + UUID.randomUUID();
Map<String, Double> membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0);
assertEquals(3, client.zadd(source, membersScores).get());

// Full range.
assertEquals(3, client.zrangestore(destination, source, new RangeByIndex(0, -1)).get());
assertEquals(
Map.of("one", 1.0, "two", 2.0, "three", 3.0),
client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Range from rank 0 to 1. In descending order of scores.
assertEquals(2, client.zrangestore(destination, source, new RangeByIndex(0, 1), true).get());
assertEquals(
Map.of("three", 3.0, "two", 2.0),
client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Incorrect range as start > stop.
assertEquals(0, client.zrangestore(destination, source, new RangeByIndex(3, 1)).get());
assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Non-existing source.
assertEquals(0, client.zrangestore(destination, key, new RangeByIndex(0, -1)).get());
assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Key exists, but it is not a set
assertEquals(OK, client.set(key, "value").get());
ExecutionException executionException =
assertThrows(
ExecutionException.class,
() -> client.zrangestore(destination, key, new RangeByIndex(3, 1)).get());
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
Expand Down Expand Up @@ -1649,6 +1610,45 @@ public void zremrangebyscore(BaseClient client) {
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
public void zrangestore_by_index(BaseClient client) {
String key = "{testKey}:" + UUID.randomUUID();
String destination = "{testKey}:" + UUID.randomUUID();
String source = "{testKey}:" + UUID.randomUUID();
Map<String, Double> membersScores = Map.of("one", 1.0, "two", 2.0, "three", 3.0);
assertEquals(3, client.zadd(source, membersScores).get());

// Full range.
assertEquals(3, client.zrangestore(destination, source, new RangeByIndex(0, -1)).get());
assertEquals(
Map.of("one", 1.0, "two", 2.0, "three", 3.0),
client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Range from rank 0 to 1. In descending order of scores.
assertEquals(2, client.zrangestore(destination, source, new RangeByIndex(0, 1), true).get());
assertEquals(
Map.of("three", 3.0, "two", 2.0),
client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Incorrect range as start > stop.
assertEquals(0, client.zrangestore(destination, source, new RangeByIndex(3, 1)).get());
assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Non-existing source.
assertEquals(0, client.zrangestore(destination, key, new RangeByIndex(0, -1)).get());
assertEquals(Map.of(), client.zrangeWithScores(destination, new RangeByIndex(0, -1)).get());

// Key exists, but it is not a set
assertEquals(OK, client.set(key, "value").get());
ExecutionException executionException =
assertThrows(
ExecutionException.class,
() -> client.zrangestore(destination, key, new RangeByIndex(3, 1)).get());
assertTrue(executionException.getCause() instanceof RequestException);
}

@SneakyThrows
@ParameterizedTest
@MethodSource("getClients")
Expand Down

0 comments on commit d1eb85b

Please sign in to comment.