Feature - rankEntry() and revRankEntry() methods added to RScoredSortedSet object

pull/4848/merge
Nikita Koksharov
parent 27161e7034
commit 08b7d75885

@ -21,6 +21,7 @@ import org.redisson.api.listener.ScoredSortedSetRemoveListener;
import org.redisson.api.mapreduce.RCollectionMapReduce;
import org.redisson.client.RedisClient;
import org.redisson.client.codec.*;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.ScoredEntry;
@ -767,6 +768,16 @@ public class RedissonScoredSortedSet<V> extends RedissonExpirable implements RSc
return commandExecutor.readAsync(getRawName(), codec, RedisCommands.ZRANK_INT, getRawName(), encode(o));
}
@Override
public RankedEntry<V> rankEntry(V o) {
return get(rankEntryAsync(o));
}
@Override
public RFuture<RankedEntry<V>> rankEntryAsync(V o) {
return commandExecutor.readAsync(getRawName(), codec, RedisCommands.ZRANK_ENTRY, getRawName(), encode(o), "WITHSCORE");
}
private ScanResult<Object> scanIterator(RedisClient client, long startPos, String pattern, int count) {
RFuture<ScanResult<Object>> f = scanIteratorAsync(client, startPos, pattern, count);
return get(f);
@ -1145,11 +1156,22 @@ public class RedissonScoredSortedSet<V> extends RedissonExpirable implements RSc
return commandExecutor.readAsync(getRawName(), codec, RedisCommands.ZREVRANK_INT, getRawName(), encode(o));
}
@Override
public RankedEntry<V> revRankEntry(V o) {
return get(revRankEntryAsync(o));
}
@Override
public RFuture<RankedEntry<V>> revRankEntryAsync(V o) {
return commandExecutor.readAsync(getRawName(), codec, RedisCommands.ZREVRANK_ENTRY, getRawName(), encode(o), "WITHSCORE");
}
@Override
public Integer revRank(V o) {
return get(revRankAsync(o));
}
@Override
public RFuture<List<Integer>> revRankAsync(Collection<V> elements) {
return commandExecutor.evalReadAsync((String) null, IntegerCodec.INSTANCE, RedisCommands.EVAL_INT_LIST,

@ -16,6 +16,7 @@
package org.redisson.api;
import org.redisson.api.mapreduce.RCollectionMapReduce;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.ScoredEntry;
import java.time.Duration;
@ -435,21 +436,39 @@ public interface RScoredSortedSet<V> extends RScoredSortedSetAsync<V>, Iterable<
int removeRangeByRank(int startIndex, int endIndex);
/**
* Returns rank of value, with the scores ordered from low to high.
* Returns rank of value, with the ranks ordered from low to high.
*
* @param o - object
* @return rank or <code>null</code> if value does not exist
*/
Integer rank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from low to high.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
RankedEntry<V> rankEntry(V value);
/**
* Returns rank of value, with the scores ordered from high to low.
* Returns rank of value, with the ranks ordered from high to low.
*
* @param o - object
* @return rank or <code>null</code> if value does not exist
*/
Integer revRank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from high to low.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
RankedEntry<V> revRankEntry(V value);
/**
* Returns ranks of elements, with the scores ordered from high to low.
*

@ -16,6 +16,7 @@
package org.redisson.api;
import org.redisson.api.RScoredSortedSet.Aggregate;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.ScoredEntry;
import java.time.Duration;
@ -404,7 +405,16 @@ public interface RScoredSortedSetAsync<V> extends RExpirableAsync, RSortableAsyn
* @return rank or <code>null</code> if value does not exist
*/
RFuture<Integer> rankAsync(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from low to high.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
RFuture<RankedEntry<V>> rankEntryAsync(V value);
/**
* Returns rank of value, with the scores ordered from high to low.
*
@ -413,6 +423,15 @@ public interface RScoredSortedSetAsync<V> extends RExpirableAsync, RSortableAsyn
*/
RFuture<Integer> revRankAsync(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from high to low.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
RFuture<RankedEntry<V>> revRankEntryAsync(V value);
/**
* Returns ranks of elements, with the scores ordered from high to low.
*

@ -16,6 +16,7 @@
package org.redisson.api;
import org.redisson.api.RScoredSortedSet.Aggregate;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.ScoredEntry;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -373,7 +374,16 @@ public interface RScoredSortedSetReactive<V> extends RExpirableReactive, RSortab
* @return rank or <code>null</code> if value does not exist
*/
Mono<Integer> rank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from low to high.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
Mono<RankedEntry<V>> rankEntry(V value);
/**
* Returns rank of value, with the scores ordered from high to low.
*
@ -382,6 +392,15 @@ public interface RScoredSortedSetReactive<V> extends RExpirableReactive, RSortab
*/
Mono<Integer> revRank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from high to low.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
Mono<RankedEntry<V>> revRankEntry(V value);
/**
* Returns ranks of elements, with the scores ordered from high to low.
*

@ -19,6 +19,7 @@ import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;
import org.redisson.api.RScoredSortedSet.Aggregate;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.ScoredEntry;
import java.time.Duration;
@ -375,7 +376,16 @@ public interface RScoredSortedSetRx<V> extends RExpirableRx, RSortableRx<Set<V>>
* @return rank or <code>null</code> if value does not exist
*/
Maybe<Integer> rank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from low to high.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
Maybe<RankedEntry<V>> rankEntry(V value);
/**
* Returns rank of value, with the scores ordered from high to low.
*
@ -384,6 +394,15 @@ public interface RScoredSortedSetRx<V> extends RExpirableRx, RSortableRx<Set<V>>
*/
Maybe<Integer> revRank(V o);
/**
* Returns rank and score of specified <code>value</code>,
* with the ranks ordered from high to low.
*
* @param value object
* @return ranked entry or <code>null</code> if value does not exist
*/
Maybe<RankedEntry<V>> revRankEntry(V value);
/**
* Returns ranks of elements, with the scores ordered from high to low.
*

@ -0,0 +1,57 @@
/**
* Copyright (c) 2013-2022 Nikita Koksharov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson.client.protocol;
import java.util.Objects;
/**
*
* @author Nikita Koksharov
*
* @param <V> value type
*/
public class RankedEntry<V> {
private final Double score;
private final Integer rank;
public RankedEntry(Integer rank, Double score) {
super();
this.score = score;
this.rank = rank;
}
public Double getScore() {
return score;
}
public Integer getRank() {
return rank;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RankedEntry<?> that = (RankedEntry<?>) o;
return Objects.equals(score, that.score) && Objects.equals(rank, that.rank);
}
@Override
public int hashCode() {
return Objects.hash(score, rank);
}
}

@ -106,8 +106,10 @@ public interface RedisCommands {
RedisStrictCommand<Double> ZSCORE = new RedisStrictCommand<Double>("ZSCORE", new DoubleReplayConvertor());
RedisStrictCommand<Long> ZRANK = new RedisStrictCommand<Long>("ZRANK");
RedisCommand<Integer> ZRANK_INT = new RedisCommand<Integer>("ZRANK", new IntegerReplayConvertor());
RedisCommand<RankedEntry<?>> ZRANK_ENTRY = new RedisCommand<>("ZRANK", new RankedEntryDecoder());
RedisStrictCommand<Long> ZREVRANK = new RedisStrictCommand<Long>("ZREVRANK");
RedisCommand<Integer> ZREVRANK_INT = new RedisCommand<Integer>("ZREVRANK", new IntegerReplayConvertor());
RedisCommand<RankedEntry<?>> ZREVRANK_ENTRY = new RedisCommand<>("ZREVRANK", new RankedEntryDecoder());
RedisCommand<Object> ZRANGE_SINGLE = new RedisCommand<Object>("ZRANGE", new ListFirstObjectDecoder());
RedisStrictCommand<Double> ZRANGE_SINGLE_SCORE = new RedisStrictCommand<Double>("ZRANGE", new ObjectFirstScoreReplayDecoder());
RedisCommand<List<Object>> ZRANGE = new RedisCommand<List<Object>>("ZRANGE", new ObjectListReplayDecoder<Object>());

@ -0,0 +1,50 @@
/**
* Copyright (c) 2013-2022 Nikita Koksharov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.redisson.client.protocol.decoder;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.DoubleCodec;
import org.redisson.client.codec.LongCodec;
import org.redisson.client.handler.State;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.RankedEntry;
import java.util.List;
/**
*
* @author Nikita Koksharov
*
*/
public class RankedEntryDecoder implements MultiDecoder<RankedEntry<?>> {
@Override
public Decoder<Object> getDecoder(Codec codec, int paramNum, State state) {
if (paramNum % 2 != 0) {
return DoubleCodec.INSTANCE.getValueDecoder();
}
return LongCodec.INSTANCE.getValueDecoder();
}
@Override
public RankedEntry<?> decode(List<Object> parts, State state) {
if (parts.isEmpty()) {
return null;
}
return new RankedEntry<>(((Long) parts.get(0)).intValue(), (Double) parts.get(1));
}
}

@ -7,6 +7,7 @@ import org.redisson.api.*;
import org.redisson.api.listener.ScoredSortedSetAddListener;
import org.redisson.client.codec.IntegerCodec;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RankedEntry;
import org.redisson.client.protocol.ScoredEntry;
import org.redisson.config.Config;
@ -26,6 +27,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class RedissonScoredSortedSetTest extends BaseTest {
@Test
public void testRankEntry() {
RScoredSortedSet<String> set = redisson.getScoredSortedSet("test");
set.add(1.1, "v1");
set.add(1.2, "v2");
set.add(1.3, "v3");
RankedEntry<String> v1 = set.rankEntry("v1");
assertThat(v1.getRank()).isEqualTo(0);
assertThat(v1.getScore()).isEqualTo(1.1);
RankedEntry<String> v3 = set.rankEntry("v3");
assertThat(v3.getRank()).isEqualTo(2);
assertThat(v3.getScore()).isEqualTo(1.3);
RankedEntry<String> v4 = set.rankEntry("v4");
assertThat(v4).isNull();
}
@Test
public void testReplace() {
RScoredSortedSet<Integer> set = redisson.getScoredSortedSet("test");

Loading…
Cancel
Save