Support ZADD params for Reactive-/RedisConnection and add addIfAbsent methods.
Closes: #1794 Original pull request: #1988.
This commit is contained in:
committed by
Mark Paluch
parent
102ee017aa
commit
4d77392c9d
@@ -1322,20 +1322,20 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[], org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
return convertAndReturn(delegate.zAdd(key, score, value), Converters.identityConverter());
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args) {
|
||||
return convertAndReturn(delegate.zAdd(key, score, value, args), Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
return convertAndReturn(delegate.zAdd(key, tuples), Converters.identityConverter());
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
return convertAndReturn(delegate.zAdd(key, tuples, args), Converters.identityConverter());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2686,20 +2686,20 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zAdd(java.lang.String, double, java.lang.String)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zAdd(java.lang.String, double, java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(String key, double score, String value) {
|
||||
return zAdd(serialize(key), score, serialize(value));
|
||||
public Boolean zAdd(String key, double score, String value, ZAddArgs args) {
|
||||
return zAdd(serialize(key), score, serialize(value), args);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zAdd(java.lang.String, java.util.Set)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#zAdd(java.lang.String, java.util.Set, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(String key, Set<StringTuple> tuples) {
|
||||
return zAdd(serialize(key), stringTupleToTuple.convert(tuples));
|
||||
public Long zAdd(String key, Set<StringTuple> tuples, ZAddArgs args) {
|
||||
return zAdd(serialize(key), stringTupleToTuple.convert(tuples), args);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -873,15 +873,15 @@ public interface DefaultedRedisConnection extends RedisConnection {
|
||||
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
return zSetCommands().zAdd(key, score, value);
|
||||
default Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args) {
|
||||
return zSetCommands().zAdd(key, score, value, args);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
return zSetCommands().zAdd(key, tuples);
|
||||
default Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
return zSetCommands().zAdd(key, tuples, args);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#zSetCommands()}}. */
|
||||
|
||||
@@ -63,9 +63,11 @@ public interface ReactiveZSetCommands {
|
||||
private final boolean upsert;
|
||||
private final boolean returnTotalChanged;
|
||||
private final boolean incr;
|
||||
private final boolean gt;
|
||||
private final boolean lt;
|
||||
|
||||
private ZAddCommand(@Nullable ByteBuffer key, List<Tuple> tuples, boolean upsert, boolean returnTotalChanged,
|
||||
boolean incr) {
|
||||
boolean incr, boolean gt, boolean lt) {
|
||||
|
||||
super(key);
|
||||
|
||||
@@ -73,6 +75,8 @@ public interface ReactiveZSetCommands {
|
||||
this.upsert = upsert;
|
||||
this.returnTotalChanged = returnTotalChanged;
|
||||
this.incr = incr;
|
||||
this.gt = gt;
|
||||
this.lt = lt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +102,7 @@ public interface ReactiveZSetCommands {
|
||||
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
return new ZAddCommand(null, new ArrayList<>(tuples), false, false, false);
|
||||
return new ZAddCommand(null, new ArrayList<>(tuples), false, false, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +115,7 @@ public interface ReactiveZSetCommands {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return new ZAddCommand(key, tuples, upsert, returnTotalChanged, incr);
|
||||
return new ZAddCommand(key, tuples, upsert, returnTotalChanged, incr, gt, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +125,7 @@ public interface ReactiveZSetCommands {
|
||||
* @return a new {@link ZAddCommand} with {@literal xx} applied.
|
||||
*/
|
||||
public ZAddCommand xx() {
|
||||
return new ZAddCommand(getKey(), tuples, false, returnTotalChanged, incr);
|
||||
return new ZAddCommand(getKey(), tuples, false, returnTotalChanged, incr, gt, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +135,7 @@ public interface ReactiveZSetCommands {
|
||||
* @return a new {@link ZAddCommand} with {@literal nx} applied.
|
||||
*/
|
||||
public ZAddCommand nx() {
|
||||
return new ZAddCommand(getKey(), tuples, true, returnTotalChanged, incr);
|
||||
return new ZAddCommand(getKey(), tuples, true, returnTotalChanged, incr, gt, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,7 +145,7 @@ public interface ReactiveZSetCommands {
|
||||
* @return a new {@link ZAddCommand} with {@literal ch} applied.
|
||||
*/
|
||||
public ZAddCommand ch() {
|
||||
return new ZAddCommand(getKey(), tuples, upsert, true, incr);
|
||||
return new ZAddCommand(getKey(), tuples, upsert, true, incr, gt, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +155,29 @@ public interface ReactiveZSetCommands {
|
||||
* @return a new {@link ZAddCommand} with {@literal incr} applied.
|
||||
*/
|
||||
public ZAddCommand incr() {
|
||||
return new ZAddCommand(getKey(), tuples, upsert, upsert, true);
|
||||
return new ZAddCommand(getKey(), tuples, upsert, upsert, true, gt, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@literal GT} mode. Constructs a new command
|
||||
* instance with all previously configured properties.
|
||||
*
|
||||
* @return a new {@link ZAddCommand} with {@literal incr} applied.
|
||||
* @since 2.5
|
||||
*/
|
||||
public ZAddCommand gt() {
|
||||
return new ZAddCommand(getKey(), tuples, upsert, upsert, incr, true, lt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@literal LT} mode. Constructs a new command
|
||||
* instance with all previously configured properties.
|
||||
*
|
||||
* @return a new {@link ZAddCommand} with {@literal incr} applied.
|
||||
* @since 2.5
|
||||
*/
|
||||
public ZAddCommand lt() {
|
||||
return new ZAddCommand(getKey(), tuples, upsert, upsert, incr, gt, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,6 +201,23 @@ public interface ReactiveZSetCommands {
|
||||
return incr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {@literal true} if {@literal GT} is set.
|
||||
* @since 2.5
|
||||
*/
|
||||
public boolean isGt() {
|
||||
return gt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if {@literal LT} is set.
|
||||
* @since 2.5
|
||||
*/
|
||||
public boolean isLt() {
|
||||
return lt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
@@ -396,6 +397,171 @@ public interface RedisZSetCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code ZADD} specific arguments. <br />
|
||||
* Looking of the {@code INCR} flag? Use the {@code ZINCRBY} operation instead.
|
||||
*
|
||||
* @since 2.3
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
*/
|
||||
class ZAddArgs {
|
||||
|
||||
private static final ZAddArgs NONE = new ZAddArgs(Collections.emptySet());
|
||||
|
||||
private final Set<Flag> flags;
|
||||
|
||||
private ZAddArgs(Set<Flag> flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return immutable {@link ZAddArgs}.
|
||||
*/
|
||||
public static ZAddArgs none() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new instance of {@link ZAddArgs} without any flags set.
|
||||
*/
|
||||
public static ZAddArgs empty() {
|
||||
return new ZAddArgs(new LinkedHashSet<>(5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new instance of {@link ZAddArgs} without {@link Flag#NX} set.
|
||||
*/
|
||||
public static ZAddArgs ifNotExists() {
|
||||
return empty().nx();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new instance of {@link ZAddArgs} without {@link Flag#NX} set.
|
||||
*/
|
||||
public static ZAddArgs ifExists() {
|
||||
return empty().xx();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only update elements that already exist.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public ZAddArgs nx() {
|
||||
|
||||
flags.add(Flag.NX);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't update already existing elements.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public ZAddArgs xx() {
|
||||
|
||||
flags.add(Flag.XX);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only update existing elements if the new score is less than the current score.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public ZAddArgs lt() {
|
||||
|
||||
flags.add(Flag.LT);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only update existing elements if the new score is greater than the current score.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public ZAddArgs gt() {
|
||||
|
||||
flags.add(Flag.GT);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only update elements that already exist.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public ZAddArgs ch() {
|
||||
|
||||
flags.add(Flag.CH);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only update elements that already exist.
|
||||
*
|
||||
* @return this.
|
||||
*/
|
||||
public boolean contains(Flag flag) {
|
||||
return flags.contains(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if no flags set.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return !flags.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ZAddArgs zAddArgs = (ZAddArgs) o;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(flags, zAddArgs.flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(flags);
|
||||
}
|
||||
|
||||
public enum Flag {
|
||||
|
||||
/**
|
||||
* Only update elements that already exist.
|
||||
*/
|
||||
XX,
|
||||
|
||||
/**
|
||||
* Don't update already existing elements.
|
||||
*/
|
||||
NX,
|
||||
|
||||
/**
|
||||
* Only update existing elements if the new score is greater than the current score.
|
||||
*/
|
||||
GT,
|
||||
|
||||
/**
|
||||
* Only update existing elements if the new score is less than the current score.
|
||||
*/
|
||||
LT,
|
||||
|
||||
/**
|
||||
* Modify the return value from the number of new elements added, to the total number of elements changed.
|
||||
*/
|
||||
CH
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@code value} to a sorted set at {@code key}, or update its {@code score} if it already exists.
|
||||
*
|
||||
@@ -406,7 +572,24 @@ public interface RedisZSetCommands {
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
*/
|
||||
@Nullable
|
||||
Boolean zAdd(byte[] key, double score, byte[] value);
|
||||
default Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
return zAdd(key, score, value, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@code value} to a sorted set at {@code key}, or update its {@code score} depending on the given
|
||||
* {@link ZAddArgs args}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param score the score.
|
||||
* @param value the value.
|
||||
* @param args must not be {@literal null} use {@link ZAddArgs#none()} instead.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
*/
|
||||
@Nullable
|
||||
Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} if it already exists.
|
||||
@@ -417,7 +600,22 @@ public interface RedisZSetCommands {
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long zAdd(byte[] key, Set<Tuple> tuples);
|
||||
default Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
return zAdd(key, tuples, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} depending on the given
|
||||
* {@link ZAddArgs args}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param tuples must not be {@literal null}.
|
||||
* @param args must not be {@literal null} use {@link ZAddArgs#none()} instead.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
*/
|
||||
Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args);
|
||||
|
||||
/**
|
||||
* Remove {@code values} from sorted set. Return number of removed elements.
|
||||
|
||||
@@ -1102,7 +1102,24 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
* @see RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
Boolean zAdd(String key, double score, String value);
|
||||
default Boolean zAdd(String key, double score, String value) {
|
||||
return zAdd(key, score, value, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the {@code value} to a sorted set at {@code key}, or update its {@code score} depending on the given
|
||||
* {@link ZAddArgs args}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param score must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @param args must not be {@literal null} use {@link ZAddArgs#none()} instead.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
* @see RedisZSetCommands#zAdd(byte[], double, byte[], ZAddArgs)
|
||||
*/
|
||||
Boolean zAdd(String key, double score, String value, ZAddArgs args);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} if it already exists.
|
||||
@@ -1113,7 +1130,24 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
* @see RedisZSetCommands#zAdd(byte[], Set)
|
||||
*/
|
||||
Long zAdd(String key, Set<StringTuple> tuples);
|
||||
default Long zAdd(String key, Set<StringTuple> tuples) {
|
||||
return zAdd(key, tuples, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} depending on the given
|
||||
* {@link ZAddArgs args}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param tuples must not be {@literal null}.
|
||||
* @param args must not be {@literal null} use {@link ZAddArgs#none()} instead.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD</a>
|
||||
* @see RedisZSetCommands#zAdd(byte[], Set, ZAddArgs)
|
||||
*/
|
||||
@Nullable
|
||||
Long zAdd(String key, Set<StringTuple> tuples, ZAddArgs args);
|
||||
|
||||
/**
|
||||
* Remove {@code values} from sorted set. Return number of removed elements.
|
||||
|
||||
@@ -54,13 +54,13 @@ class JedisClusterZSetCommands implements RedisZSetCommands {
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
try {
|
||||
return JedisConverters.toBoolean(connection.getCluster().zadd(key, score, value));
|
||||
return JedisConverters.toBoolean(connection.getCluster().zadd(key, score, value, JedisConverters.toZAddParams(args)));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
@@ -68,16 +68,16 @@ class JedisClusterZSetCommands implements RedisZSetCommands {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
try {
|
||||
return connection.getCluster().zadd(key, JedisConverters.toTupleMap(tuples));
|
||||
return connection.getCluster().zadd(key, JedisConverters.toTupleMap(tuples), JedisConverters.toZAddParams(args));
|
||||
} catch (Exception ex) {
|
||||
throw convertJedisAccessException(ex);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import redis.clients.jedis.ScanParams;
|
||||
import redis.clients.jedis.SortingParams;
|
||||
import redis.clients.jedis.params.GeoRadiusParam;
|
||||
import redis.clients.jedis.params.SetParams;
|
||||
import redis.clients.jedis.params.ZAddParams;
|
||||
import redis.clients.jedis.util.SafeEncoder;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -61,6 +62,7 @@ import org.springframework.data.redis.connection.RedisStringCommands.BitOperatio
|
||||
import org.springframework.data.redis.connection.RedisStringCommands.SetOption;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range.Boundary;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs;
|
||||
import org.springframework.data.redis.connection.SortParameters;
|
||||
import org.springframework.data.redis.connection.SortParameters.Order;
|
||||
import org.springframework.data.redis.connection.SortParameters.Range;
|
||||
@@ -652,6 +654,42 @@ public abstract class JedisConverters extends Converters {
|
||||
return ObjectUtils.caseInsensitiveValueOf(GeoUnit.values(), metricToUse.getAbbreviation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link ZAddArgs} to {@link ZAddParams}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @return new instance of {@link ZAddParams}.
|
||||
* @since 2.5
|
||||
*/
|
||||
static ZAddParams toZAddParams(ZAddArgs source) {
|
||||
|
||||
if (!source.isEmpty()) {
|
||||
return new ZAddParams();
|
||||
}
|
||||
|
||||
ZAddParams target = new ZAddParams() {
|
||||
|
||||
{
|
||||
if (source.contains(ZAddArgs.Flag.GT)) {
|
||||
addParam("gt");
|
||||
}
|
||||
if (source.contains(ZAddArgs.Flag.LT)) {
|
||||
addParam("lt");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (source.contains(ZAddArgs.Flag.XX)) {
|
||||
target.xx();
|
||||
}
|
||||
if (source.contains(ZAddArgs.Flag.NX)) {
|
||||
target.nx();
|
||||
}
|
||||
if (source.contains(ZAddArgs.Flag.CH)) {
|
||||
target.ch();
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link GeoRadiusCommandArgs} into {@link GeoRadiusParam}.
|
||||
|
||||
@@ -21,12 +21,14 @@ import redis.clients.jedis.MultiKeyPipelineBase;
|
||||
import redis.clients.jedis.ScanParams;
|
||||
import redis.clients.jedis.ScanResult;
|
||||
import redis.clients.jedis.ZParams;
|
||||
import redis.clients.jedis.params.ZAddParams;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs.Flag;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.KeyBoundCursor;
|
||||
import org.springframework.data.redis.core.ScanIteration;
|
||||
@@ -53,27 +55,27 @@ class JedisZSetCommands implements RedisZSetCommands {
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return connection.invoke().from(BinaryJedis::zadd, MultiKeyPipelineBase::zadd, key, score, value)
|
||||
return connection.invoke().from(BinaryJedis::zadd, MultiKeyPipelineBase::zadd, key, score, value, JedisConverters.toZAddParams(args))
|
||||
.get(JedisConverters::toBoolean);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
return connection.invoke().just(BinaryJedis::zadd, MultiKeyPipelineBase::zadd, key,
|
||||
JedisConverters.toTupleMap(tuples));
|
||||
JedisConverters.toTupleMap(tuples), JedisConverters.toZAddParams(args));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -102,6 +102,12 @@ class LettuceReactiveZSetCommands implements ReactiveZSetCommands {
|
||||
} else {
|
||||
args = ZAddArgs.Builder.xx();
|
||||
}
|
||||
if(command.isGt()) {
|
||||
args = args == null ? ZAddArgs.Builder.gt() : args.gt();
|
||||
}
|
||||
if(command.isLt()) {
|
||||
args = args == null ? ZAddArgs.Builder.lt() : args.lt();
|
||||
}
|
||||
}
|
||||
|
||||
ScoredValue<ByteBuffer>[] values = (ScoredValue<ByteBuffer>[]) command.getTuples().stream()
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs.Flag;
|
||||
import org.springframework.data.redis.connection.convert.Converters;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.KeyBoundCursor;
|
||||
@@ -50,29 +51,29 @@ class LettuceZSetCommands implements RedisZSetCommands {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[])
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], double, byte[], org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value) {
|
||||
public Boolean zAdd(byte[] key, double score, byte[] value, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return connection.invoke().from(RedisSortedSetAsyncCommands::zadd, key, score, value)
|
||||
return connection.invoke().from(RedisSortedSetAsyncCommands::zadd, key, LettuceZSetCommands.toZAddArgs(args), score, value)
|
||||
.get(LettuceConverters.longToBoolean());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set)
|
||||
* @see org.springframework.data.redis.connection.RedisZSetCommands#zAdd(byte[], java.util.Set, org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs)
|
||||
*/
|
||||
@Override
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(tuples, "Tuples must not be null!");
|
||||
|
||||
return connection.invoke().just(RedisSortedSetAsyncCommands::zadd, key,
|
||||
return connection.invoke().just(RedisSortedSetAsyncCommands::zadd, key, LettuceZSetCommands.toZAddArgs(args),
|
||||
LettuceConverters.toObjects(tuples).toArray());
|
||||
}
|
||||
|
||||
@@ -568,4 +569,37 @@ class LettuceZSetCommands implements RedisZSetCommands {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {@link ZAddArgs} to {@link io.lettuce.core.ZAddArgs}.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.5
|
||||
*/
|
||||
private static io.lettuce.core.ZAddArgs toZAddArgs(ZAddArgs source) {
|
||||
|
||||
io.lettuce.core.ZAddArgs target = new io.lettuce.core.ZAddArgs();
|
||||
|
||||
if(!source.isEmpty()) {
|
||||
return target;
|
||||
}
|
||||
|
||||
if(source.contains(Flag.XX)) {
|
||||
target.xx();
|
||||
}
|
||||
if(source.contains(Flag.NX)) {
|
||||
target.nx();
|
||||
}
|
||||
if(source.contains(Flag.GT)) {
|
||||
target.gt();
|
||||
}
|
||||
if(source.contains(Flag.LT)) {
|
||||
target.lt();
|
||||
}
|
||||
if(source.contains(Flag.CH)) {
|
||||
target.ch();
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,18 @@ public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
Boolean add(V value, double score);
|
||||
|
||||
/**
|
||||
* Add {@code value} to a sorted set at {@code key} if it does not already exists.
|
||||
*
|
||||
* @param score the score.
|
||||
* @param value the value.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD NX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Boolean addIfAbsent(V value, double score);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at the bound key, or update its {@code score} if it already exists.
|
||||
*
|
||||
@@ -58,6 +70,17 @@ public interface BoundZSetOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
Long add(Set<TypedTuple<V>> tuples);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key} if it does not already exists.
|
||||
*
|
||||
* @param tuples must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD NX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long addIfAbsent(Set<TypedTuple<V>> tuples);
|
||||
|
||||
/**
|
||||
* Remove {@code values} from sorted set. Return number of removed elements.
|
||||
*
|
||||
|
||||
@@ -60,6 +60,15 @@ class DefaultBoundZSetOperations<K, V> extends DefaultBoundKeyOperations<K> impl
|
||||
return ops.add(getKey(), value, score);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#addIfAbsent(java.lang.Object, double)
|
||||
*/
|
||||
@Override
|
||||
public Boolean addIfAbsent(V value, double score) {
|
||||
return ops.addIfAbsent(getKey(), value, score);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#add(java.util.Set)
|
||||
@@ -69,6 +78,15 @@ class DefaultBoundZSetOperations<K, V> extends DefaultBoundKeyOperations<K> impl
|
||||
return ops.add(getKey(), tuples);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#addIfAbsent(java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public Long addIfAbsent(Set<TypedTuple<V>> tuples) {
|
||||
return ops.addIfAbsent(getKey(), tuples);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundZSetOperations#incrementScore(java.lang.Object, double)
|
||||
|
||||
@@ -24,6 +24,8 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Limit;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Weights;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ZSetOperations}.
|
||||
@@ -48,10 +50,31 @@ class DefaultZSetOperations<K, V> extends AbstractOperations<K, V> implements ZS
|
||||
*/
|
||||
@Override
|
||||
public Boolean add(K key, V value, double score) {
|
||||
return add(key, value, score, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ZSetOperations#addIfAbsent(java.lang.Object, java.lang.Object, double)
|
||||
*/
|
||||
@Override
|
||||
public Boolean addIfAbsent(K key, V value, double score) {
|
||||
return add(key, value, score, ZAddArgs.ifNotExists());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @param args never {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @since 2.5
|
||||
*/
|
||||
@Nullable
|
||||
protected Boolean add(K key, V value, double score, ZAddArgs args) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawValue = rawValue(value);
|
||||
return execute(connection -> connection.zAdd(rawKey, score, rawValue), true);
|
||||
return execute(connection -> connection.zAdd(rawKey, score, rawValue, args), true);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -60,10 +83,31 @@ class DefaultZSetOperations<K, V> extends AbstractOperations<K, V> implements ZS
|
||||
*/
|
||||
@Override
|
||||
public Long add(K key, Set<TypedTuple<V>> tuples) {
|
||||
return add(key, tuples, ZAddArgs.none());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ZSetOperations#addIfAbsent(java.lang.Object, java.util.Set)
|
||||
*/
|
||||
@Override
|
||||
public Long addIfAbsent(K key, Set<TypedTuple<V>> tuples) {
|
||||
return add(key, tuples, ZAddArgs.ifNotExists());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key must not be {@literal null}.
|
||||
* @param tuples must not be {@literal null}.
|
||||
* @param args never {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
* @since 2.5
|
||||
*/
|
||||
@Nullable
|
||||
protected Long add(K key, Set<TypedTuple<V>> tuples, ZAddArgs args) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
Set<Tuple> rawValues = rawTupleValues(tuples);
|
||||
return execute(connection -> connection.zAdd(rawKey, rawValues), true);
|
||||
return execute(connection -> connection.zAdd(rawKey, rawValues, args), true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -47,6 +47,19 @@ public interface ZSetOperations<K, V> {
|
||||
|
||||
@Nullable
|
||||
Double getScore();
|
||||
|
||||
/**
|
||||
* Create a new {@link TypedTuple}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @param score can be {@literal null}.
|
||||
* @param <V>
|
||||
* @return new instance of {@link TypedTuple}.
|
||||
* @since 2.5
|
||||
*/
|
||||
static <V> TypedTuple<V> of(V value, @Nullable Double score) {
|
||||
return new DefaultTypedTuple<>(value, score);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +74,19 @@ public interface ZSetOperations<K, V> {
|
||||
@Nullable
|
||||
Boolean add(K key, V value, double score);
|
||||
|
||||
/**
|
||||
* Add {@code value} to a sorted set at {@code key} if it does not already exists.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param score the score.
|
||||
* @param value the value.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD NX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Boolean addIfAbsent(K key, V value, double score);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} if it already exists.
|
||||
*
|
||||
@@ -72,6 +98,18 @@ public interface ZSetOperations<K, V> {
|
||||
@Nullable
|
||||
Long add(K key, Set<TypedTuple<V>> tuples);
|
||||
|
||||
/**
|
||||
* Add {@code tuples} to a sorted set at {@code key} if it does not already exists.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param tuples must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @since 2.5
|
||||
* @see <a href="https://redis.io/commands/zadd">Redis Documentation: ZADD NX</a>
|
||||
*/
|
||||
@Nullable
|
||||
Long addIfAbsent(K key, Set<TypedTuple<V>> tuples);
|
||||
|
||||
/**
|
||||
* Remove {@code values} from sorted set. Return number of removed elements.
|
||||
*
|
||||
|
||||
@@ -288,6 +288,18 @@ public class DefaultRedisZSet<E> extends AbstractRedisCollection<E> implements R
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.support.collections.RedisZSet#addIfAbsent(java.lang.Object, double)
|
||||
*/
|
||||
@Override
|
||||
public boolean addIfAbsent(E e, double score) {
|
||||
|
||||
Boolean result = boundZSetOps.addIfAbsent(e, score);
|
||||
checkResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.AbstractCollection#clear()
|
||||
|
||||
@@ -144,6 +144,27 @@ public interface RedisZSet<E> extends RedisCollection<E>, Set<E> {
|
||||
*/
|
||||
boolean add(E e);
|
||||
|
||||
/**
|
||||
* Adds an element to the set using the {@link #getDefaultScore() default score} if the element does not already exists.
|
||||
*
|
||||
* @param e element to add
|
||||
* @return true if a new element was added, false otherwise (only the score has been updated)
|
||||
* @since 2.5
|
||||
*/
|
||||
default boolean addIfAbsent(E e) {
|
||||
return addIfAbsent(e, getDefaultScore());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an element to the set with the given score if the element does not already exists.
|
||||
*
|
||||
* @param e element to add
|
||||
* @param score element score
|
||||
* @return true if a new element was added, false otherwise (only the score has been updated)
|
||||
* @since 2.5
|
||||
*/
|
||||
boolean addIfAbsent(E e, double score);
|
||||
|
||||
/**
|
||||
* Count number of elements within sorted set with value between {@code Range#min} and {@code Range#max} applying
|
||||
* lexicographical ordering.
|
||||
|
||||
@@ -39,7 +39,6 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.domain.Range.Bound;
|
||||
@@ -59,6 +58,7 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Aggregate;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Limit;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs;
|
||||
import org.springframework.data.redis.connection.SortParameters.Order;
|
||||
import org.springframework.data.redis.connection.StringRedisConnection.StringTuple;
|
||||
import org.springframework.data.redis.connection.ValueEncoding.RedisValueEncoding;
|
||||
@@ -1314,8 +1314,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.rPush("PopList", "world"));
|
||||
connection.lSet("PopList", 1, "cruel");
|
||||
actual.add(connection.lRange("PopList", 0, -1));
|
||||
verifyResults(
|
||||
Arrays.asList(1L, 2L, 3L, Arrays.asList("hello", "cruel", "world")));
|
||||
verifyResults(Arrays.asList(1L, 2L, 3L, Arrays.asList("hello", "cruel", "world")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1491,8 +1490,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.sAdd("myset", "foo", "bar"));
|
||||
actual.add(connection.sAdd("myset", "baz"));
|
||||
actual.add(connection.sMembers("myset"));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { 2L, 1L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { 2L, 1L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1564,8 +1562,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.sAdd("myset", "foo"));
|
||||
actual.add(connection.sAdd("myset", "bar"));
|
||||
actual.add(connection.sPop("myset"));
|
||||
assertThat(new HashSet<>(Arrays.asList("foo", "bar")).contains((String) getResults().get(2)))
|
||||
.isTrue();
|
||||
assertThat(new HashSet<>(Arrays.asList("foo", "bar")).contains((String) getResults().get(2))).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-688
|
||||
@@ -1645,8 +1642,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.sAdd("otherset", "bar"));
|
||||
actual.add(connection.sAdd("otherset", "baz"));
|
||||
actual.add(connection.sUnion("myset", "otherset"));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { 1L, 1L, 1L, 1L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { 1L, 1L, 1L, 1L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1657,8 +1653,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.sAdd("otherset", "baz"));
|
||||
actual.add(connection.sUnionStore("thirdset", "myset", "otherset"));
|
||||
actual.add(connection.sMembers("thirdset"));
|
||||
verifyResults(Arrays.asList(
|
||||
new Object[] { 1L, 1L, 1L, 1L, 3L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { 1L, 1L, 1L, 1L, 3L, new HashSet<>(Arrays.asList("foo", "bar", "baz")) }));
|
||||
}
|
||||
|
||||
// ZSet
|
||||
@@ -1668,8 +1664,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRange("myset", 0, -1));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("James", "Bob")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("James", "Bob")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1682,8 +1677,52 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", strTuples));
|
||||
actual.add(connection.zAdd("myset".getBytes(), tuples));
|
||||
actual.add(connection.zRange("myset", 0, -1));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { 2L, 1L, new LinkedHashSet<>(Arrays.asList("James", "Bob", "Joe")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { 2L, 1L, new LinkedHashSet<>(Arrays.asList("James", "Bob", "Joe")) }));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void zAddNX() {
|
||||
|
||||
actual.add(connection.zAdd("myset", 1, "Bob", ZAddArgs.ifNotExists()));
|
||||
actual.add(connection.zAdd("myset", 2, "Bob", ZAddArgs.ifNotExists()));
|
||||
|
||||
verifyResults(Arrays.asList(true, false));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void zAddXX() {
|
||||
|
||||
actual.add(connection.zAdd("myset", 1, "Bob", ZAddArgs.ifExists()));
|
||||
actual.add(connection.zAdd("myset", 1, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 2, "Bob", ZAddArgs.ifExists()));
|
||||
|
||||
verifyResults(Arrays.asList(false, true, false));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void testZAddMultipleNX() {
|
||||
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
|
||||
Set<StringTuple> strTuples = new HashSet<>();
|
||||
strTuples.add(new DefaultStringTuple("Bob".getBytes(), "Bob", 2.0));
|
||||
strTuples.add(new DefaultStringTuple("James".getBytes(), "James", 1.0));
|
||||
|
||||
actual.add(connection.zAdd("myset", strTuples, ZAddArgs.ifNotExists()));
|
||||
verifyResults(Arrays.asList(true, 1L));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void testZAddMultipleXX() {
|
||||
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
|
||||
Set<StringTuple> strTuples = new HashSet<>();
|
||||
strTuples.add(new DefaultStringTuple("Bob".getBytes(), "Bob", 2.0));
|
||||
strTuples.add(new DefaultStringTuple("James".getBytes(), "James", 2.0));
|
||||
|
||||
actual.add(connection.zAdd("myset", strTuples, ZAddArgs.ifNotExists()));
|
||||
verifyResults(Arrays.asList(true, 1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1783,8 +1822,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRangeByScore("myset", 1, 1));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("James")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("James")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1792,8 +1830,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRangeByScore("myset", 1d, 3d, 1, -1));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1801,8 +1838,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRangeByScoreWithScores("myset", 2d, 5d));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(
|
||||
Arrays.asList(new DefaultStringTuple("Bob".getBytes(), "Bob", 2d))) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true,
|
||||
new LinkedHashSet<>(Arrays.asList(new DefaultStringTuple("Bob".getBytes(), "Bob", 2d))) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1810,8 +1847,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRangeByScoreWithScores("myset", 1d, 5d, 0, 1));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(
|
||||
Arrays.asList(new DefaultStringTuple("James".getBytes(), "James", 1d))) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true,
|
||||
new LinkedHashSet<>(Arrays.asList(new DefaultStringTuple("James".getBytes(), "James", 1d))) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1819,8 +1856,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 2, "Bob"));
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRevRange("myset", 0, -1));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1838,8 +1874,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset".getBytes(), 2, "Bob".getBytes()));
|
||||
actual.add(connection.zAdd("myset".getBytes(), 1, "James".getBytes()));
|
||||
actual.add(connection.zRevRangeByScore("myset", 0d, 3d, 0, 5));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1847,8 +1882,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset".getBytes(), 2, "Bob".getBytes()));
|
||||
actual.add(connection.zAdd("myset".getBytes(), 1, "James".getBytes()));
|
||||
actual.add(connection.zRevRangeByScore("myset", 0d, 3d));
|
||||
verifyResults(Arrays
|
||||
.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("Bob", "James")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1856,8 +1890,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset".getBytes(), 2, "Bob".getBytes()));
|
||||
actual.add(connection.zAdd("myset".getBytes(), 1, "James".getBytes()));
|
||||
actual.add(connection.zRevRangeByScoreWithScores("myset", 0d, 3d, 0, 1));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(
|
||||
Arrays.asList(new DefaultStringTuple("Bob".getBytes(), "Bob", 2d))) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true,
|
||||
new LinkedHashSet<>(Arrays.asList(new DefaultStringTuple("Bob".getBytes(), "Bob", 2d))) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1886,8 +1920,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("myset", 1, "James"));
|
||||
actual.add(connection.zRem("myset", "James"));
|
||||
actual.add(connection.zRange("myset", 0L, -1L));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { true, true, 1L, new LinkedHashSet<>(Arrays.asList("Bob")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, 1L, new LinkedHashSet<>(Arrays.asList("Bob")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1927,7 +1960,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zRemRangeByLex("myset", Range.range().gte("alpha").lte("omega")));
|
||||
|
||||
actual.add(connection.zRange("myset", 0L, -1L));
|
||||
verifyResults(Arrays.asList( true, true, true, true, true, true, true, true, true, true, 6L, new LinkedHashSet<>(Arrays.asList("ALPHA", "aaaa", "zap", "zip"))));
|
||||
verifyResults(Arrays.asList(true, true, true, true, true, true, true, true, true, true, 6L,
|
||||
new LinkedHashSet<>(Arrays.asList("ALPHA", "aaaa", "zap", "zip"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1937,8 +1971,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zRemRangeByScore("myset", 0d, 1d));
|
||||
actual.add(connection.zRange("myset", 0L, -1L));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { true, true, 1L, new LinkedHashSet<>(Collections
|
||||
.singletonList("Bob")) }));
|
||||
Arrays.asList(new Object[] { true, true, 1L, new LinkedHashSet<>(Collections.singletonList("Bob")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1981,8 +2014,8 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.zAdd("otherset", 4, "James"));
|
||||
actual.add(connection.zUnionStore("thirdset", Aggregate.MAX, new int[] { 2, 3 }, "myset", "otherset"));
|
||||
actual.add(connection.zRangeWithScores("thirdset", 0, -1));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, true, true, true, 3L, new LinkedHashSet<>(Arrays.asList(
|
||||
new DefaultStringTuple("Bob".getBytes(), "Bob", 4d),
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, true, true, true, 3L,
|
||||
new LinkedHashSet<>(Arrays.asList(new DefaultStringTuple("Bob".getBytes(), "Bob", 4d),
|
||||
new DefaultStringTuple("Joe".getBytes(), "Joe", 8d),
|
||||
new DefaultStringTuple("James".getBytes(), "James", 12d))) }));
|
||||
}
|
||||
@@ -2054,8 +2087,7 @@ public abstract class AbstractConnectionIntegrationTests {
|
||||
actual.add(connection.hSet("test", "key", "2"));
|
||||
actual.add(connection.hSet("test", "key2", "2"));
|
||||
actual.add(connection.hKeys("test"));
|
||||
verifyResults(
|
||||
Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("key", "key2")) }));
|
||||
verifyResults(Arrays.asList(new Object[] { true, true, new LinkedHashSet<>(Arrays.asList("key", "key2")) }));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1233,14 +1233,14 @@ public class DefaultStringRedisConnectionTests {
|
||||
|
||||
@Test
|
||||
public void testZAddBytes() {
|
||||
doReturn(true).when(nativeConnection).zAdd(fooBytes, 3d, barBytes);
|
||||
doReturn(true).when(nativeConnection).zAdd(eq(fooBytes), eq(3d), eq(barBytes), any());
|
||||
actual.add(connection.zAdd(fooBytes, 3d, barBytes));
|
||||
verifyResults(Collections.singletonList(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZAdd() {
|
||||
doReturn(true).when(nativeConnection).zAdd(fooBytes, 3d, barBytes);
|
||||
doReturn(true).when(nativeConnection).zAdd(eq(fooBytes), eq(3d), eq(barBytes), any());
|
||||
actual.add(connection.zAdd(foo, 3d, bar));
|
||||
verifyResults(Collections.singletonList(true));
|
||||
}
|
||||
@@ -1249,7 +1249,7 @@ public class DefaultStringRedisConnectionTests {
|
||||
public void testZAddMultipleBytes() {
|
||||
Set<Tuple> tuples = new HashSet<>();
|
||||
tuples.add(new DefaultTuple(barBytes, 3.0));
|
||||
doReturn(1L).when(nativeConnection).zAdd(fooBytes, tuples);
|
||||
doReturn(1L).when(nativeConnection).zAdd(eq(fooBytes), eq(tuples), any());
|
||||
actual.add(connection.zAdd(fooBytes, tuples));
|
||||
verifyResults(Collections.singletonList(1L));
|
||||
}
|
||||
@@ -1260,7 +1260,7 @@ public class DefaultStringRedisConnectionTests {
|
||||
tuples.add(new DefaultTuple(barBytes, 3.0));
|
||||
Set<StringTuple> strTuples = new HashSet<>();
|
||||
strTuples.add(new DefaultStringTuple(barBytes, bar, 3.0));
|
||||
doReturn(1L).when(nativeConnection).zAdd(fooBytes, tuples);
|
||||
doReturn(1L).when(nativeConnection).zAdd(eq(fooBytes), eq(tuples), any());
|
||||
actual.add(connection.zAdd(foo, strTuples));
|
||||
verifyResults(Collections.singletonList(1L));
|
||||
}
|
||||
|
||||
@@ -255,8 +255,8 @@ class RedisConnectionUnitTests {
|
||||
return delegate.getNativeConnection();
|
||||
}
|
||||
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples) {
|
||||
return delegate.zAdd(key, tuples);
|
||||
public Long zAdd(byte[] key, Set<Tuple> tuples, ZAddArgs args) {
|
||||
return delegate.zAdd(key, tuples, args);
|
||||
}
|
||||
|
||||
public void subscribe(MessageListener listener, byte[]... channels) {
|
||||
|
||||
@@ -17,9 +17,14 @@ package org.springframework.data.redis.core;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.Range;
|
||||
import org.springframework.data.redis.connection.RedisZSetCommands.ZAddArgs;
|
||||
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultZSetOperations}.
|
||||
@@ -46,4 +51,21 @@ class DefaultZSetOperationsUnitTests {
|
||||
|
||||
template.verify().zRemRangeByLex(eq(template.serializeKey("key")), eq(range));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void delegatesAddIfAbsent() {
|
||||
|
||||
zSetOperations.addIfAbsent("key", "value", 1D);
|
||||
|
||||
template.verify().zAdd(eq(template.serializeKey("key")), eq(1D), eq(template.serializeKey("value")),
|
||||
eq(ZAddArgs.ifNotExists()));
|
||||
}
|
||||
|
||||
@Test // GH-1794
|
||||
void delegatesAddIfAbsentForTuples() {
|
||||
|
||||
zSetOperations.addIfAbsent("key", Collections.singleton(TypedTuple.of("value", 1D)));
|
||||
|
||||
template.verify().zAdd(eq(template.serializeKey("key")), any(Set.class), eq(ZAddArgs.ifNotExists()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.springframework.data.redis.test.extension.parametrized.ParameterizedR
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
* @author Andrey Shlykov
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractRedisZSetTestIntegration<T> extends AbstractRedisCollectionIntegrationTests<T> {
|
||||
|
||||
@@ -677,4 +678,13 @@ public abstract class AbstractRedisZSetTestIntegration<T> extends AbstractRedisC
|
||||
cursor.close();
|
||||
|
||||
}
|
||||
|
||||
@ParameterizedRedisTest // GH-1794
|
||||
void testZAddIfAbsentWorks() {
|
||||
|
||||
T t1 = getT();
|
||||
|
||||
assertThat(zSet.addIfAbsent(t1, 1)).isTrue();
|
||||
assertThat(zSet.addIfAbsent(t1, 1)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user