diff --git a/src/main/java/org/redisson/RedissonScoredSortedSet.java b/src/main/java/org/redisson/RedissonScoredSortedSet.java index bba0dfd73..8c51b17b5 100644 --- a/src/main/java/org/redisson/RedissonScoredSortedSet.java +++ b/src/main/java/org/redisson/RedissonScoredSortedSet.java @@ -26,9 +26,9 @@ import org.redisson.client.RedisClient; import org.redisson.client.codec.StringCodec; import org.redisson.client.protocol.RedisCommand; import org.redisson.client.protocol.RedisCommands; +import org.redisson.client.protocol.ScoredEntry; import org.redisson.client.protocol.convertor.BooleanReplayConvertor; import org.redisson.client.protocol.decoder.ListScanResult; -import org.redisson.client.protocol.decoder.ScoredEntry; import org.redisson.core.RScoredSortedSet; import io.netty.util.concurrent.Future; @@ -46,6 +46,10 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc @Override public Future addAsync(double score, V object) { + // String should be encoded as String to let lex functions work properly + if (object instanceof String) { + return commandExecutor.writeAsync(getName(), StringCodec.INSTANCE, RedisCommands.ZADD, getName(), BigDecimal.valueOf(score).toPlainString(), object); + } return commandExecutor.writeAsync(getName(), RedisCommands.ZADD, getName(), BigDecimal.valueOf(score).toPlainString(), object); } @@ -90,15 +94,25 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc } @Override - public Double getScore(Object o) { + public Double getScore(V o) { return get(getScoreAsync(o)); } @Override - public Future getScoreAsync(Object o) { + public Future getScoreAsync(V o) { return commandExecutor.readAsync(getName(), RedisCommands.ZSCORE, getName(), o); } + @Override + public Integer rank(V o) { + return get(rankAsync(o)); + } + + @Override + public Future rankAsync(V o) { + return commandExecutor.readAsync(getName(), RedisCommands.ZRANK, getName(), o); + } + private ListScanResult scanIterator(RedisClient client, long startPos) { return commandExecutor.read(client, getName(), RedisCommands.ZSCAN, getName(), startPos); } @@ -259,9 +273,32 @@ public class RedissonScoredSortedSet extends RedissonExpirable implements RSc } @Override - public Future>> entryRangeAsync(int startIndex, - int endIndex) { + public Future>> entryRangeAsync(int startIndex, int endIndex) { return commandExecutor.readAsync(getName(), RedisCommands.ZRANGE_ENTRY, getName(), startIndex, endIndex, "WITHSCORES"); } + @Override + public Integer lexCount(V fromElement, boolean fromInclusive, V toElement, boolean toInclusive) { + return get(lexCountAsync(fromElement, fromInclusive, toElement, toInclusive)); + } + + @Override + public Future lexCountAsync(V fromElement, boolean fromInclusive, V toElement, boolean toInclusive) { + String fromValue = fromElement.toString(); + if (fromInclusive) { + fromValue = "[" + fromValue; + } else { + fromValue = "(" + fromValue; + } + + String toValue = toElement.toString(); + if (toInclusive) { + toValue = "[" + toValue; + } else { + toValue = "(" + toValue; + } + + return commandExecutor.readAsync(getName(), RedisCommands.ZLEXCOUNT, getName(), fromValue, toValue); + } + } diff --git a/src/main/java/org/redisson/client/protocol/RedisCommands.java b/src/main/java/org/redisson/client/protocol/RedisCommands.java index a3f4e6c17..4d9000830 100644 --- a/src/main/java/org/redisson/client/protocol/RedisCommands.java +++ b/src/main/java/org/redisson/client/protocol/RedisCommands.java @@ -37,7 +37,6 @@ import org.redisson.client.protocol.decoder.NestedMultiDecoder; import org.redisson.client.protocol.decoder.ObjectListReplayDecoder; import org.redisson.client.protocol.decoder.ObjectMapReplayDecoder; import org.redisson.client.protocol.decoder.ObjectSetReplayDecoder; -import org.redisson.client.protocol.decoder.ScoredEntry; import org.redisson.client.protocol.decoder.ScoredSortedSetReplayDecoder; import org.redisson.client.protocol.decoder.ScoredSortedSetScanReplayDecoder; import org.redisson.client.protocol.decoder.StringDataDecoder; @@ -52,8 +51,10 @@ public interface RedisCommands { RedisCommand ZADD = new RedisCommand("ZADD", new BooleanAmountReplayConvertor(), 3); RedisCommand ZREM = new RedisCommand("ZREM", new BooleanAmountReplayConvertor(), 2); RedisStrictCommand ZCARD = new RedisStrictCommand("ZCARD", new IntegerReplayConvertor()); + RedisStrictCommand ZLEXCOUNT = new RedisStrictCommand("ZLEXCOUNT", new IntegerReplayConvertor()); RedisCommand ZSCORE_CONTAINS = new RedisCommand("ZSCORE", new BooleanNotNullReplayConvertor(), 2); RedisStrictCommand ZSCORE = new RedisStrictCommand("ZSCORE", new DoubleReplayConvertor()); + RedisStrictCommand ZRANK = new RedisStrictCommand("ZRANK", new IntegerReplayConvertor()); RedisCommand> ZRANGE = new RedisCommand>("ZRANGE", new ObjectListReplayDecoder()); RedisCommand>> ZRANGE_ENTRY = new RedisCommand>>("ZRANGE", new ScoredSortedSetReplayDecoder()); RedisCommand> ZSCAN = new RedisCommand>("ZSCAN", new NestedMultiDecoder(new ObjectListReplayDecoder(), new ScoredSortedSetScanReplayDecoder()), ValueType.OBJECT); diff --git a/src/main/java/org/redisson/client/protocol/decoder/ScoredEntry.java b/src/main/java/org/redisson/client/protocol/ScoredEntry.java similarity index 97% rename from src/main/java/org/redisson/client/protocol/decoder/ScoredEntry.java rename to src/main/java/org/redisson/client/protocol/ScoredEntry.java index 398fc799b..9bbd56801 100644 --- a/src/main/java/org/redisson/client/protocol/decoder/ScoredEntry.java +++ b/src/main/java/org/redisson/client/protocol/ScoredEntry.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.redisson.client.protocol.decoder; +package org.redisson.client.protocol; public class ScoredEntry { diff --git a/src/main/java/org/redisson/client/protocol/decoder/ScoredSortedSetReplayDecoder.java b/src/main/java/org/redisson/client/protocol/decoder/ScoredSortedSetReplayDecoder.java index bfa322082..5a77210ce 100644 --- a/src/main/java/org/redisson/client/protocol/decoder/ScoredSortedSetReplayDecoder.java +++ b/src/main/java/org/redisson/client/protocol/decoder/ScoredSortedSetReplayDecoder.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import org.redisson.client.handler.State; +import org.redisson.client.protocol.ScoredEntry; import io.netty.buffer.ByteBuf; diff --git a/src/main/java/org/redisson/core/RScoredSortedSet.java b/src/main/java/org/redisson/core/RScoredSortedSet.java index 5d55e4902..12bb19aef 100644 --- a/src/main/java/org/redisson/core/RScoredSortedSet.java +++ b/src/main/java/org/redisson/core/RScoredSortedSet.java @@ -17,11 +17,15 @@ package org.redisson.core; import java.util.Collection; -import org.redisson.client.protocol.decoder.ScoredEntry; +import org.redisson.client.protocol.ScoredEntry; public interface RScoredSortedSet extends RScoredSortedSetAsync, Iterable, RExpirable { - Double getScore(Object o); + Integer lexCount(V fromElement, boolean fromInclusive, V toElement, boolean toInclusive); + + Integer rank(V o); + + Double getScore(V o); boolean add(double score, V object); diff --git a/src/main/java/org/redisson/core/RScoredSortedSetAsync.java b/src/main/java/org/redisson/core/RScoredSortedSetAsync.java index ef89c3551..8802fa45f 100644 --- a/src/main/java/org/redisson/core/RScoredSortedSetAsync.java +++ b/src/main/java/org/redisson/core/RScoredSortedSetAsync.java @@ -17,13 +17,17 @@ package org.redisson.core; import java.util.Collection; -import org.redisson.client.protocol.decoder.ScoredEntry; +import org.redisson.client.protocol.ScoredEntry; import io.netty.util.concurrent.Future; public interface RScoredSortedSetAsync extends RExpirableAsync { - Future getScoreAsync(Object o); + Future lexCountAsync(V fromElement, boolean fromInclusive, V toElement, boolean toInclusive); + + Future rankAsync(V o); + + Future getScoreAsync(V o); Future addAsync(double score, V object); diff --git a/src/test/java/org/redisson/RedissonScoredSortedSetTest.java b/src/test/java/org/redisson/RedissonScoredSortedSetTest.java index 4af77772d..f64096ff5 100644 --- a/src/test/java/org/redisson/RedissonScoredSortedSetTest.java +++ b/src/test/java/org/redisson/RedissonScoredSortedSetTest.java @@ -1,10 +1,7 @@ package org.redisson; -import io.netty.util.concurrent.Future; - import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -16,13 +13,43 @@ import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; -import org.redisson.client.protocol.decoder.ScoredEntry; -import org.redisson.core.RMap; +import org.redisson.client.protocol.ScoredEntry; import org.redisson.core.RScoredSortedSet; import org.redisson.core.RSortedSet; +import io.netty.util.concurrent.Future; + public class RedissonScoredSortedSetTest extends BaseTest { + @Test + public void testRank() { + RScoredSortedSet set = redisson.getScoredSortedSet("simple"); + set.add(0.1, "a"); + set.add(0.2, "b"); + set.add(0.3, "c"); + set.add(0.4, "d"); + set.add(0.5, "e"); + set.add(0.6, "f"); + set.add(0.7, "g"); + + Assert.assertEquals(3, (int)set.rank("d")); + } + + @Test + public void testLexCount() { + RScoredSortedSet set = redisson.getScoredSortedSet("simple"); + set.add(0, "a"); + set.add(0, "b"); + set.add(0, "c"); + set.add(0, "d"); + set.add(0, "e"); + set.add(0, "f"); + set.add(0, "g"); + + Assert.assertEquals(5, (int)set.lexCount("b", true, "f", true)); + Assert.assertEquals(3, (int)set.lexCount("b", false, "f", false)); + } + @Test public void testAddAsync() throws InterruptedException, ExecutionException { RScoredSortedSet set = redisson.getScoredSortedSet("simple");