Support HRANDFIELD command via RedisMap.

Add randomKey() and randomEntry() to RedisHash.
Update documentation and align methods with java terminology around keys vs. fields in hashes.
Move Converters off their custom Map.Entry implementation and use SimpleImmutableEntry instead.
Switch code that creates Map.Entry to the newly introduced Converters.entryOf method.

See: #2048
Original Pull Request: #2104
This commit is contained in:
Christoph Strobl
2021-06-30 11:11:36 +02:00
parent a523b821c5
commit 4c4c96e9cf
15 changed files with 185 additions and 144 deletions

View File

@@ -173,8 +173,8 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
hashOps.put(key, key1, val1);
hashOps.put(key, key2, val2);
assertThat(hashOps.randomField(key)).isIn(key1, key2);
assertThat(hashOps.randomFields(key, 2)).hasSize(2).contains(key1, key2);
assertThat(hashOps.randomKey(key)).isIn(key1, key2);
assertThat(hashOps.randomKeys(key, 2)).hasSize(2).contains(key1, key2);
}
@ParameterizedRedisTest // GH-2048
@@ -190,7 +190,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
hashOps.put(key, key1, val1);
hashOps.put(key, key2, val2);
Map.Entry<HK, HV> entry = hashOps.randomValue(key);
Map.Entry<HK, HV> entry = hashOps.randomEntry(key);
if (entry.getKey().equals(key1)) {
assertThat(entry.getValue()).isEqualTo(val1);
@@ -198,7 +198,7 @@ public class DefaultHashOperationsIntegrationTests<K, HK, HV> {
assertThat(entry.getValue()).isEqualTo(val2);
}
Map<HK, HV> values = hashOps.randomValues(key, 10);
Map<HK, HV> values = hashOps.randomEntries(key, 10);
assertThat(values).hasSize(2).containsEntry(key1, val1).containsEntry(key2, val2);
}
}

View File

@@ -18,11 +18,11 @@ package org.springframework.data.redis.core;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.Assumptions.*;
import org.springframework.data.redis.connection.convert.Converters;
import reactor.test.StepVerifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -251,13 +251,13 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.expectNext(true) //
.verifyComplete();
hashOperations.randomField(key) //
hashOperations.randomKey(key) //
.as(StepVerifier::create) //
.assertNext(actual -> {
assertThat(actual).isIn(hashkey1, hashkey2);
}).verifyComplete();
hashOperations.randomFields(key, -10) //
hashOperations.randomKeys(key, -10) //
.collectList().as(StepVerifier::create) //
.assertNext(actual -> {
assertThat(actual).hasSize(10);
@@ -286,7 +286,7 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.expectNext(true) //
.verifyComplete();
hashOperations.randomValue(key) //
hashOperations.randomEntry(key) //
.as(StepVerifier::create) //
.assertNext(actual -> {
@@ -297,7 +297,7 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
}
}).verifyComplete();
hashOperations.randomValues(key, -10) //
hashOperations.randomEntries(key, -10) //
.collectList().as(StepVerifier::create) //
.assertNext(actual -> {
assertThat(actual).hasSize(10);
@@ -462,8 +462,8 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.as(StepVerifier::create) //
.consumeNextWith(list -> {
Entry<HK, HV> entry1 = Collections.singletonMap(hashkey1, hashvalue1).entrySet().iterator().next();
Entry<HK, HV> entry2 = Collections.singletonMap(hashkey2, hashvalue2).entrySet().iterator().next();
Entry<HK, HV> entry1 = Converters.entryOf(hashkey1, hashvalue1);
Entry<HK, HV> entry2 = Converters.entryOf(hashkey2, hashvalue2);
assertThat(list).containsExactlyInAnyOrder(entry1, entry2);
}) //
@@ -489,8 +489,8 @@ public class DefaultReactiveHashOperationsIntegrationTests<K, HK, HV> {
.as(StepVerifier::create) //
.consumeNextWith(list -> {
Entry<HK, HV> entry1 = Collections.singletonMap(hashkey1, hashvalue1).entrySet().iterator().next();
Entry<HK, HV> entry2 = Collections.singletonMap(hashkey2, hashvalue2).entrySet().iterator().next();
Entry<HK, HV> entry1 = Converters.entryOf(hashkey1, hashvalue1);
Entry<HK, HV> entry2 = Converters.entryOf(hashkey2, hashvalue2);
assertThat(list).containsExactlyInAnyOrder(entry1, entry2);
}) //

View File

@@ -20,6 +20,7 @@ import static org.assertj.core.api.Assumptions.*;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
@@ -28,17 +29,19 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.assertj.core.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.DoubleAsStringObjectFactory;
import org.springframework.data.redis.LongAsStringObjectFactory;
import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.RawObjectFactory;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.test.condition.EnabledOnCommand;
import org.springframework.data.redis.test.extension.parametrized.MethodSource;
import org.springframework.data.redis.test.extension.parametrized.ParameterizedRedisTest;
@@ -458,4 +461,39 @@ public abstract class AbstractRedisMapIntegrationTests<K, V> {
}
cursor.close();
}
@ParameterizedRedisTest // GH-2048
@EnabledOnCommand("HRANDFIELD")
public void randomKeyFromHash() {
K k1 = getKey();
K k2 = getKey();
V v1 = getValue();
V v2 = getValue();
map.put(k1, v1);
map.put(k2, v2);
assertThat(map.randomKey()).isIn(k1, k2);
}
@ParameterizedRedisTest // GH-2048
@EnabledOnCommand("HRANDFIELD")
public void randomEntryFromHash() {
Assumptions.assumeThat(this.valueFactory).isNotInstanceOf(RawObjectFactory.class);
K k1 = getKey();
K k2 = getKey();
V v1 = getValue();
V v2 = getValue();
map.put(k1, v1);
map.put(k2, v2);
assertThat(map.randomEntry()).isIn(new AbstractMap.SimpleImmutableEntry(k1, v1),
new AbstractMap.SimpleImmutableEntry(k2, v2));
}
}