DATAREDIS-1196 - Add support for LPOS command.
Original pull request: #563.
This commit is contained in:
committed by
Mark Paluch
parent
1a025fea46
commit
76cbe5124d
@@ -702,6 +702,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return convertAndReturn(delegate.lPop(key), identityConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return convertAndReturn(delegate.lPos(key, element, rank, count), identityConverter);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
@@ -2138,6 +2147,15 @@ public class DefaultStringRedisConnection implements StringRedisConnection, Deco
|
||||
return convertAndReturn(delegate.lPop(serialize(key)), bytesToString);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#lPos(java.lang.String, java.lang.String, java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(String key, String element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return lPos(serialize(key), serialize(element), rank, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.StringRedisConnection#lPush(java.lang.String, java.lang.String[])
|
||||
|
||||
@@ -621,6 +621,13 @@ public interface DefaultedRedisConnection extends RedisConnection {
|
||||
return listCommands().rPush(key, values);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#listCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
default List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
return listCommands().lPos(key, element, rank, count);
|
||||
}
|
||||
|
||||
/** @deprecated in favor of {@link RedisConnection#listCommands()}}. */
|
||||
@Override
|
||||
@Deprecated
|
||||
|
||||
@@ -312,6 +312,125 @@ public interface ReactiveListCommands {
|
||||
*/
|
||||
Flux<BooleanResponse<RangeCommand>> lTrim(Publisher<RangeCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code LPOS} command parameters.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
class LPosCommand extends KeyCommand {
|
||||
|
||||
private final ByteBuffer element;
|
||||
private final @Nullable Integer count;
|
||||
private final @Nullable Integer rank;
|
||||
|
||||
private LPosCommand(@Nullable ByteBuffer key, ByteBuffer element, @Nullable Integer count, @Nullable Integer rank) {
|
||||
|
||||
super(key);
|
||||
this.element = element;
|
||||
this.count = count;
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link LPosCommand} for given {@literal element}.
|
||||
*
|
||||
* @param element
|
||||
* @return a new {@link LPosCommand} for {@literal element}.
|
||||
*/
|
||||
public static LPosCommand lPosOf(ByteBuffer element) {
|
||||
return new LPosCommand(null, element, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal key}. Constructs a new command instance with all previously configured properties.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @return a new {@link LPosCommand} with {@literal key} applied.
|
||||
*/
|
||||
public LPosCommand from(ByteBuffer key) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
return new LPosCommand(key, element, count, rank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal count} parameter specifying the number of matches to return. Constructs a new command
|
||||
* instance with all previously configured properties.
|
||||
*
|
||||
* @param count can be {@literal null}.
|
||||
* @return a new {@link LPosCommand} with {@literal count} applied.
|
||||
*/
|
||||
public LPosCommand count(Integer count) {
|
||||
return new LPosCommand(getKey(), element, count, rank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@literal rank} parameter specifying the "rank" of the first element to return. Constructs a new
|
||||
* command instance with all previously configured properties.
|
||||
*
|
||||
* @param rank can be {@literal null}.
|
||||
* @return a new {@link LPosCommand} with {@literal count} applied.
|
||||
*/
|
||||
public LPosCommand rank(Integer rank) {
|
||||
return new LPosCommand(getKey(), element, count, rank);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getRank() {
|
||||
return rank;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteBuffer getElement() {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first index of the {@literal element} from list at {@literal key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element
|
||||
* @return a {@link Mono} emitting the elements index.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
default Mono<Long> lPos(ByteBuffer key, ByteBuffer element) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return lPos(LPosCommand.lPosOf(element).from(key)).next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get indices of the {@literal element} from list at {@link LPosCommand#getKey()}.
|
||||
*
|
||||
* @param command must not be {@literal null}.
|
||||
* @return a {@link Flux} emitting the elements indices one by one.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
default Flux<Long> lPos(LPosCommand command) {
|
||||
return lPos(Mono.just(command)).map(NumericResponse::getOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get indices of the {@literal element} from list at {@link LPosCommand#getKey()}.
|
||||
*
|
||||
* @param commands must not be {@literal null}.
|
||||
* @return a {@link Flux} emitting the elements indices one by one.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lindex">Redis Documentation: LINDEX</a>
|
||||
*/
|
||||
Flux<NumericResponse<LPosCommand, Long>> lPos(Publisher<LPosCommand> commands);
|
||||
|
||||
/**
|
||||
* {@code LINDEX} command parameters.
|
||||
*
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.redis.connection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* List-specific commands supported by Redis.
|
||||
@@ -46,6 +47,36 @@ public interface RedisListCommands {
|
||||
@Nullable
|
||||
Long rPush(byte[] key, byte[]... values);
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
@Nullable
|
||||
default Long lPos(byte[] key, byte[] element) {
|
||||
return CollectionUtils.firstElement(lPos(key, element, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @param rank specifies the "rank" of the first element to return, in case there are multiple matches. A rank of 1
|
||||
* means to return the first match, 2 to return the second match, and so forth.
|
||||
* @param count number of matches to return.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count);
|
||||
|
||||
/**
|
||||
* Prepend {@code values} to {@code key}.
|
||||
*
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.data.redis.core.types.Expiration;
|
||||
import org.springframework.data.redis.core.types.RedisClientInfo;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Convenience extension of {@link RedisConnection} that accepts and returns {@link String}s instead of byte arrays.
|
||||
@@ -685,6 +686,36 @@ public interface StringRedisConnection extends RedisConnection {
|
||||
*/
|
||||
Long rPush(String key, String... values);
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
@Nullable
|
||||
default Long lPos(String key, String element) {
|
||||
return CollectionUtils.firstElement(lPos(key, element, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of matching elements inside the list stored at given {@literal key}. <br />
|
||||
* Requires Redis 6.0.6.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param element must not be {@literal null}.
|
||||
* @param rank specifies the "rank" of the first element to return, in case there are multiple matches. A rank of 1
|
||||
* means to return the first match, 2 to return the second match, and so forth.
|
||||
* @param count number of matches to return.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
* @since 2.4
|
||||
*/
|
||||
List<Long> lPos(String key, String element, @Nullable Integer rank, @Nullable Integer count);
|
||||
|
||||
/**
|
||||
* Prepend {@code values} to {@code key}.
|
||||
*
|
||||
|
||||
@@ -20,9 +20,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.data.redis.connection.jedis.JedisClusterConnection.JedisMultiKeyClusterCommandCallback;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -55,6 +57,19 @@ class JedisClusterListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -20,7 +20,9 @@ import redis.clients.jedis.Protocol;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -60,6 +62,19 @@ class JedisListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
throw new InvalidDataAccessApiUsageException("LPOS is not supported by jedis.");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -1136,6 +1136,7 @@ public class LettuceConnection extends AbstractRedisConnection {
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LINSERT, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LLEN, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPUSH, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPOS, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LPUSHX, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(LREM, IntegerOutput.class);
|
||||
COMMAND_OUTPUT_TYPE_MAPPING.put(PTTL, IntegerOutput.class);
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.LPosArgs;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisListCommands;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -61,6 +64,47 @@ class LettuceListCommands implements RedisListCommands {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#l{lPos(byte[], byte[], java.lang.Integer, java.lang.Integer)
|
||||
*/
|
||||
@Override
|
||||
public List<Long> lPos(byte[] key, byte[] element, @Nullable Integer rank, @Nullable Integer count) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
Assert.notNull(element, "Element must not be null!");
|
||||
|
||||
LPosArgs args = new LPosArgs();
|
||||
if (rank != null) {
|
||||
args.rank(rank);
|
||||
}
|
||||
try {
|
||||
if (isPipelined()) {
|
||||
if (count != null) {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpos(key, element, count, args)));
|
||||
} else {
|
||||
pipeline(connection.newLettuceResult(getAsyncConnection().lpos(key, element, args)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isQueueing()) {
|
||||
if (count != null) {
|
||||
transaction(connection.newLettuceResult(getAsyncConnection().lpos(key, element, count, args)));
|
||||
} else {
|
||||
transaction(connection.newLettuceResult(getAsyncConnection().lpos(key, element, args)));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (count != null) {
|
||||
return getConnection().lpos(key, element, count, args);
|
||||
}
|
||||
|
||||
return Collections.singletonList(getConnection().lpos(key, element, args));
|
||||
} catch (Exception ex) {
|
||||
throw convertLettuceAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.RedisListCommands#lPush(byte[], byte[][])
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.redis.connection.lettuce;
|
||||
|
||||
import io.lettuce.core.LPosArgs;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -146,8 +147,32 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
|
||||
LettuceConverters.getLowerBoundIndex(range), //
|
||||
LettuceConverters.getUpperBoundIndex(range));
|
||||
|
||||
return result
|
||||
.map(LettuceConverters::stringToBoolean).map(value -> new BooleanResponse<>(command, value));
|
||||
return result.map(LettuceConverters::stringToBoolean).map(value -> new BooleanResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.connection.ReactiveListCommands#lPos(org.reactivestreams.Publisher)
|
||||
*/
|
||||
@Override
|
||||
public Flux<NumericResponse<LPosCommand, Long>> lPos(Publisher<LPosCommand> commands) {
|
||||
|
||||
return connection.execute(cmd -> Flux.from(commands).concatMap(command -> {
|
||||
|
||||
LPosArgs args = new LPosArgs();
|
||||
if (command.getRank() != null) {
|
||||
args.rank(command.getRank());
|
||||
}
|
||||
|
||||
Flux<Long> values;
|
||||
if (command.getCount() != null) {
|
||||
values = cmd.lpos(command.getKey(), command.getElement(), command.getCount(), args);
|
||||
} else {
|
||||
values = cmd.lpos(command.getKey(), command.getElement(), args).flux();
|
||||
}
|
||||
|
||||
return values.map(value -> new NumericResponse<>(command, value));
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -238,7 +263,8 @@ class LettuceReactiveListCommands implements ReactiveListCommands {
|
||||
Assert.notNull(command.getDirection(), "Direction must not be null!");
|
||||
|
||||
Mono<ByteBuffer> popResult = ObjectUtils.nullSafeEquals(Direction.RIGHT, command.getDirection())
|
||||
? cmd.rpop(command.getKey()) : cmd.lpop(command.getKey());
|
||||
? cmd.rpop(command.getKey())
|
||||
: cmd.lpop(command.getKey());
|
||||
|
||||
return popResult.map(value -> new ByteBufferResponse<>(command, value));
|
||||
}));
|
||||
|
||||
@@ -169,6 +169,28 @@ public interface BoundListOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
V index(long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long indexOf(V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long lastIndexOf(V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at the bound key.
|
||||
*
|
||||
|
||||
@@ -55,6 +55,24 @@ class DefaultBoundListOperations<K, V> extends DefaultBoundKeyOperations<K> impl
|
||||
return ops.index(getKey(), index);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#indexOf(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long indexOf(V value) {
|
||||
return ops.indexOf(getKey(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#lastIndexOf(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long lastIndexOf(V value) {
|
||||
return ops.lastIndexOf(getKey(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.BoundListOperations#leftPop()
|
||||
|
||||
@@ -53,6 +53,34 @@ class DefaultListOperations<K, V> extends AbstractOperations<K, V> implements Li
|
||||
}, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#indexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long indexOf(K key, V value) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawValue = rawValue(value);
|
||||
return execute(connection -> connection.lPos(rawKey, rawValue), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#lastIndexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Long lastIndexOf(K key, V value) {
|
||||
|
||||
byte[] rawKey = rawKey(key);
|
||||
byte[] rawValue = rawValue(value);
|
||||
return execute(connection -> {
|
||||
|
||||
List<Long> indexes = connection.lPos(rawKey, rawValue, -1, null);
|
||||
return CollectionUtils.firstElement(indexes);
|
||||
}, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ListOperations#leftPop(java.lang.Object)
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.function.Function;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands;
|
||||
import org.springframework.data.redis.connection.ReactiveListCommands.LPosCommand;
|
||||
import org.springframework.data.redis.connection.RedisListCommands.Position;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -232,6 +233,30 @@ class DefaultReactiveListOperations<K, V> implements ReactiveListOperations<K, V
|
||||
return createMono(connection -> connection.lIndex(rawKey(key), index).map(this::readValue));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#indexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> indexOf(K key, V value) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createMono(connection -> connection.lPos(rawKey(key), rawValue(value)));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#lastIndexOf(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Long> lastIndexOf(K key, V value) {
|
||||
|
||||
Assert.notNull(key, "Key must not be null!");
|
||||
|
||||
return createMono(connection -> connection.lPos(LPosCommand.lPosOf(rawValue(value)).from(rawKey(key)).rank(-1)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.redis.core.ReactiveListOperations#leftPop(java.lang.Object)
|
||||
*/
|
||||
|
||||
@@ -213,6 +213,30 @@ public interface ListOperations<K, V> {
|
||||
@Nullable
|
||||
V index(K key, long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long indexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction or when not contained in list.
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Long lastIndexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at {@code key}.
|
||||
*
|
||||
|
||||
@@ -20,7 +20,6 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Redis list specific operations.
|
||||
@@ -197,6 +196,30 @@ public interface ReactiveListOperations<K, V> {
|
||||
*/
|
||||
Mono<V> index(K key, long index);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Mono<Long> indexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified value in the list at at {@code key}. <br />
|
||||
* Requires Redis 6.0.6
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value must not be {@literal null}.
|
||||
* @return
|
||||
* @since 2.4
|
||||
* @see <a href="https://redis.io/commands/lpos">Redis Documentation: LPOS</a>
|
||||
*/
|
||||
Mono<Long> lastIndexOf(K key, V value);
|
||||
|
||||
/**
|
||||
* Removes and returns first element in list stored at {@code key}.
|
||||
*
|
||||
|
||||
@@ -250,7 +250,9 @@ public class DefaultRedisList<E> extends AbstractRedisCollection<E> implements R
|
||||
*/
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Long index = listOps.indexOf((E) o);
|
||||
return index != null ? index.intValue() : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,7 +261,9 @@ public class DefaultRedisList<E> extends AbstractRedisCollection<E> implements R
|
||||
*/
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Long index = listOps.lastIndexOf((E) o);
|
||||
return index != null ? index.intValue() : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user