diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 957a5c928..1bafa35f7 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -2393,4 +2393,44 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return delegate.getSentinelConnection(); } + @Override + public Set zRangeByScore(String key, String min, String max) { + Set results = delegate.zRangeByScore(serialize(key), min, max); + if (isFutureConversion()) { + addResultConverter(identityConverter); + } + return results; + } + + @Override + public Set zRangeByScore(String key, String min, String max, long offset, long count) { + Set results = delegate.zRangeByScore(serialize(key), min, max, offset, count); + if (isFutureConversion()) { + addResultConverter(identityConverter); + } + return results; + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + + Set results = delegate.zRangeByScore(key, min, max); + if (isFutureConversion()) { + addResultConverter(identityConverter); + } + + return results; + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + + Set results = delegate.zRangeByScore(key, min, max, offset, count); + if (isFutureConversion()) { + addResultConverter(identityConverter); + } + + return results; + } + } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java index 10c004264..5c343465a 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java @@ -25,6 +25,8 @@ import org.springframework.data.redis.core.ScanOptions; * * @author Costin Leau * @author Christoph Strobl + * @author Thomas Darimont + * @author David Liu */ public interface RedisZSetCommands { @@ -346,4 +348,29 @@ public interface RedisZSetCommands { * @return */ Cursor zScan(byte[] key, ScanOptions options); + + /** + * Get elements where score is between {@code min} and {@code max} from sorted set. + * + * @since 1.5 + * @see http://redis.io/commands/zrangebyscore + * @param key + * @param begin + * @param end + * @return + */ + Set zRangeByScore(byte[] key, String min, String max); + + /** + * Get elements in range from {@code begin} to {@code end} where score is between {@code min} and {@code max} from + * sorted set. + * + * @since 1.5 + * @see http://redis.io/commands/zrangebyscore + * @param key + * @param begin + * @param end + * @return + */ + Set zRangeByScore(byte[] key, String min, String max, long offset, long count); } diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java index 680a0debd..9b0c70d5e 100644 --- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java @@ -33,6 +33,9 @@ import org.springframework.data.redis.serializer.RedisSerializer; * * @author Costin Leau * @author Christoph Strobl + * @author Thomas Darimont + * @author David Liu + * * @see RedisCallback * @see RedisSerializer * @see StringRedisTemplate @@ -345,4 +348,24 @@ public interface StringRedisConnection extends RedisConnection { * @return */ Cursor zScan(String key, ScanOptions options); + + /** + * @since 1.5 + * @param key + * @param min + * @param max + * @return + */ + Set zRangeByScore(String key, String min, String max); + + /** + * @since 1.5 + * @param key + * @param min + * @param max + * @param offset + * @param count + * @return + */ + Set zRangeByScore(String key, String min, String max, long offset, long count); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index 453481ba9..4de105420 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -3163,4 +3163,42 @@ public class JedisConnection extends AbstractRedisConnection { protected Jedis getJedis(RedisNode node) { return new Jedis(node.getHost(), node.getPort()); } + + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + + try { + String keyStr = new String(key, "UTF-8"); + if (isPipelined()) { + pipeline(new JedisResult(pipeline.zrangeByScore(keyStr, min, max))); + return null; + } + if (isQueueing()) { + transaction(new JedisResult(transaction.zrangeByScore(keyStr, min, max))); + return null; + } + return JedisConverters.stringSetToByteSet().convert(jedis.zrangeByScore(keyStr, min, max)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + + try { + String keyStr = new String(key, "UTF-8"); + if (isPipelined()) { + pipeline(new JedisResult(pipeline.zrangeByScore(keyStr, min, max, (int) offset, (int) count))); + return null; + } + if (isQueueing()) { + transaction(new JedisResult(transaction.zrangeByScore(keyStr, min, max, (int) offset, (int) count))); + return null; + } + return JedisConverters.stringSetToByteSet().convert(jedis.zrangeByScore(keyStr, min, max, (int) offset, (int) count)); + } catch (Exception ex) { + throw convertJedisAccessException(ex); + } + } } diff --git a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java index b375cbd22..eb36ea8ef 100644 --- a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java @@ -1282,5 +1282,14 @@ public class JredisConnection extends AbstractRedisConnection { public Cursor> hScan(byte[] key, ScanOptions options) { throw new UnsupportedOperationException("'HSCAN' command is not uspported for jredis"); } + + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + throw new UnsupportedOperationException("'zRangeByScore' command is not uspported for jredis"); + } + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + throw new UnsupportedOperationException("'zRangeByScore' command is not uspported for jredis"); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index d4abc4ddc..30f5b58b1 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -3616,4 +3616,44 @@ public class LettuceConnection extends AbstractRedisConnection { } } + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + + try { + if (isPipelined()) { + pipeline(new LettuceResult(getAsyncConnection().zrangebyscore(key, min, max), + LettuceConverters.bytesListToBytesSet())); + return null; + } + if (isQueueing()) { + transaction(new LettuceTxResult(getConnection().zrangebyscore(key, min, max), + LettuceConverters.bytesListToBytesSet())); + return null; + } + return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, min, max)); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + + try { + if (isPipelined()) { + pipeline(new LettuceResult(getAsyncConnection().zrangebyscore(key, min, max, offset, count), + LettuceConverters.bytesListToBytesSet())); + return null; + } + if (isQueueing()) { + transaction(new LettuceTxResult(getConnection().zrangebyscore(key, min, max, offset, count), + LettuceConverters.bytesListToBytesSet())); + return null; + } + return LettuceConverters.toBytesSet(getConnection().zrangebyscore(key, min, max, offset, count)); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + } diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java index e10b0dea4..2addbea8e 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java @@ -2472,4 +2472,35 @@ public class SrpConnection extends AbstractRedisConnection { return arrays.toArray(); } + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + + try { + String keyStr = new String(key, "UTF-8"); + if (isPipelined()) { + pipeline(new SrpResult(pipeline.zrangebyscore(keyStr, min, max, null, EMPTY_PARAMS_ARRAY), + SrpConverters.repliesToBytesSet())); + return null; + } + return SrpConverters.toBytesSet(client.zrangebyscore(keyStr, min, max, null, EMPTY_PARAMS_ARRAY).data()); + } catch (Exception ex) { + throw convertSrpAccessException(ex); + } + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + + try { + String keyStr = new String(key, "UTF-8"); + Object[] limit = limitParams(offset, count); + if (isPipelined()) { + pipeline(new SrpResult(pipeline.zrangebyscore(keyStr, min, max, null, limit), SrpConverters.repliesToBytesSet())); + return null; + } + return SrpConverters.toBytesSet(client.zrangebyscore(keyStr, min, max, null, limit).data()); + } catch (Exception ex) { + throw convertSrpAccessException(ex); + } + } } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java index 662619412..e8dc1f973 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultZSetOperations.java @@ -29,6 +29,8 @@ import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; * * @author Costin Leau * @author Christoph Strobl + * @author Thomas Darimont + * @author David Liu */ class DefaultZSetOperations extends AbstractOperations implements ZSetOperations { @@ -392,4 +394,32 @@ class DefaultZSetOperations extends AbstractOperations implements ZS } }); } + + public Set rangeByScore(K key, final String min, final String max) { + + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + + public Set doInRedis(RedisConnection connection) { + return connection.zRangeByScore(rawKey, min, max); + } + }, true); + + return rawValues; + } + + public Set rangeByScore(K key, final String min, final String max, final long offset, final long count) { + + final byte[] rawKey = rawKey(key); + + Set rawValues = execute(new RedisCallback>() { + + public Set doInRedis(RedisConnection connection) { + return connection.zRangeByScore(rawKey, min, max, offset, count); + } + }, true); + + return rawValues; + } } diff --git a/src/test/java/org/springframework/data/redis/connection/RedisConnectionUnitTests.java b/src/test/java/org/springframework/data/redis/connection/RedisConnectionUnitTests.java index ea5df3bc7..935023ae4 100644 --- a/src/test/java/org/springframework/data/redis/connection/RedisConnectionUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/RedisConnectionUnitTests.java @@ -35,6 +35,7 @@ import org.springframework.util.ObjectUtils; /** * @author Christoph Strobl + * @author Thomas Darimont * @author David Liu */ public class RedisConnectionUnitTests { @@ -790,5 +791,15 @@ public class RedisConnectionUnitTests { public T evalSha(byte[] scriptSha, ReturnType returnType, int numKeys, byte[]... keysAndArgs) { return delegate.evalSha(scriptSha, returnType, numKeys, keysAndArgs); } + + @Override + public Set zRangeByScore(byte[] key, String min, String max) { + return delegate.zRangeByScore(key, min, max); + } + + @Override + public Set zRangeByScore(byte[] key, String min, String max, long offset, long count) { + return delegate.zRangeByScore(key, min, max, offset, count); + } } } diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java index 17718fa31..729e65739 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionIntegrationTests.java @@ -61,6 +61,7 @@ import redis.clients.jedis.JedisPoolConfig; * @author Jennifer Hickey * @author Thomas Darimont * @author Christoph Strobl + * @author David Liu */ @RunWith(RelaxedJUnit4ClassRunner.class) @ContextConfiguration @@ -400,4 +401,19 @@ public class JedisConnectionIntegrationTests extends AbstractConnectionIntegrati .sentinel("127.0.0.1", 26379).sentinel("127.0.0.1", 26380)); assertThat(connection.getSentinelConnection(), notNullValue()); } + + /** + * @see DATAREDIS-106 + */ + @Test + public void zRangeByScoreTest() { + + connection.zAdd("myzset", 1, "one"); + connection.zAdd("myzset", 2, "two"); + connection.zAdd("myzset", 3, "three"); + + Set zRangeByScore = connection.zRangeByScore("myzset", "(1", "2"); + + assertEquals("two", new String(zRangeByScore.iterator().next())); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java index 12b6240ab..45745181f 100644 --- a/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionIntegrationTests.java @@ -22,6 +22,7 @@ import static org.springframework.data.redis.SpinBarrier.*; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.hamcrest.core.AllOf; @@ -52,6 +53,7 @@ import com.lambdaworks.redis.RedisAsyncConnection; * @author Jennifer Hickey * @author Thomas Darimont * @author Christoph Strobl + * @author David Liu */ @RunWith(RelaxedJUnit4ClassRunner.class) @ContextConfiguration @@ -311,5 +313,20 @@ public class LettuceConnectionIntegrationTests extends AbstractConnectionIntegra assertEquals(Arrays.asList(new Object[] { "key1", "arg1" }), Arrays.asList(new Object[] { new String(scriptResults.get(0)), new String(scriptResults.get(1)) })); } + + /** + * @see DATAREDIS-106 + */ + @Test + public void zRangeByScoreTest() { + + connection.zAdd("myzset", 1, "one"); + connection.zAdd("myzset", 2, "two"); + connection.zAdd("myzset", 3, "three"); + + Set zRangeByScore = connection.zRangeByScore("myzset", "(1", "2"); + + assertEquals("two", new String(zRangeByScore.iterator().next())); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java index 2d1911dbc..ec21dbd0e 100644 --- a/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/srp/SrpConnectionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import java.util.Arrays; import java.util.List; +import java.util.Set; import org.hamcrest.core.Is; import org.hamcrest.core.IsInstanceOf; @@ -40,6 +41,8 @@ import redis.reply.Reply; * * @author Costin Leau * @author Jennifer Hickey + * @author Thomas Darimont + * @author David Liu */ @RunWith(RelaxedJUnit4ClassRunner.class) @ContextConfiguration @@ -117,4 +120,18 @@ public class SrpConnectionIntegrationTests extends AbstractConnectionIntegration Arrays.asList(new Object[] { new String(scriptResults.get(0)), new String(scriptResults.get(1)) })); } + /** + * @see DATAREDIS-106 + */ + @Test + public void zRangeByScoreTest() { + + connection.zAdd("myzset", 1, "one"); + connection.zAdd("myzset", 2, "two"); + connection.zAdd("myzset", 3, "three"); + + Set zRangeByScore = connection.zRangeByScore("myzset", "(1", "2"); + + Assert.assertEquals("two", new String(zRangeByScore.iterator().next())); + } }