Skip to content

Commit ff37da5

Browse files
christophstroblThomas Darimont
authored andcommitted
DATAREDIS-378 - Add support for ZRANGEBYLEX.
We now support ZRANGEBYLEX on RedisConnection and StringRedisConnection when using the Jedis driver. The upper and lower bounds can be defined using the Range type which will be converted to the according binary representation including prefix and/or infinite operators. range().gt("a") => (a + range().gte("a") => [a + range().lt("z") => - (z range().lte("z") => - [z range().gte("a").lt("z") => [a (z
1 parent b916ff7 commit ff37da5

File tree

11 files changed

+587
-11
lines changed

11 files changed

+587
-11
lines changed

src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -2494,4 +2494,63 @@ public void pfMerge(String destinationKey, String... sourceKeys) {
24942494
this.pfMerge(serialize(destinationKey), serializeMulti(sourceKeys));
24952495
}
24962496

2497+
/*
2498+
* (non-Javadoc)
2499+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[])
2500+
*/
2501+
@Override
2502+
public Set<byte[]> zRangeByLex(byte[] key) {
2503+
return delegate.zRangeByLex(key);
2504+
}
2505+
2506+
/*
2507+
* (non-Javadoc)
2508+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
2509+
*/
2510+
@Override
2511+
public Set<byte[]> zRangeByLex(byte[] key, Range range) {
2512+
return delegate.zRangeByLex(key, range);
2513+
}
2514+
2515+
/*
2516+
* (non-Javadoc)
2517+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
2518+
*/
2519+
@Override
2520+
public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
2521+
return delegate.zRangeByLex(key, range, limit);
2522+
}
2523+
2524+
/*
2525+
* (non-Javadoc)
2526+
* @see org.springframework.data.redis.connection.StringRedisConnection#zRangeByLex(java.lang.String)
2527+
*/
2528+
@Override
2529+
public Set<String> zRangeByLex(String key) {
2530+
return this.zRangeByLex(key, Range.unbounded());
2531+
}
2532+
2533+
/*
2534+
* (non-Javadoc)
2535+
* @see org.springframework.data.redis.connection.StringRedisConnection#zRangeByLex(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Range)
2536+
*/
2537+
@Override
2538+
public Set<String> zRangeByLex(String key, Range range) {
2539+
return this.zRangeByLex(key, range, null);
2540+
}
2541+
2542+
/*
2543+
* (non-Javadoc)
2544+
* @see org.springframework.data.redis.connection.StringRedisConnection#zRangeByLex(java.lang.String, org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
2545+
*/
2546+
@Override
2547+
public Set<String> zRangeByLex(String key, Range range, Limit limit) {
2548+
2549+
Set<byte[]> results = delegate.zRangeByLex(serialize(key), range);
2550+
if (isFutureConversion()) {
2551+
addResultConverter(byteSetToStringSet);
2552+
}
2553+
return byteSetToStringSet.convert(results);
2554+
}
2555+
24972556
}

src/main/java/org/springframework/data/redis/connection/RedisZSetCommands.java

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919

2020
import org.springframework.data.redis.core.Cursor;
2121
import org.springframework.data.redis.core.ScanOptions;
22+
import org.springframework.util.Assert;
2223

2324
/**
2425
* ZSet(SortedSet)-specific commands supported by Redis.
@@ -47,6 +48,163 @@ public interface Tuple extends Comparable<Double> {
4748
Double getScore();
4849
}
4950

51+
/**
52+
* {@link Range} defines {@literal min} and {@literal max} values to retrieve from a {@literal ZSET}.
53+
*
54+
* @author Christoph Strobl
55+
* @since 1.6
56+
*/
57+
public class Range {
58+
59+
Boundary min;
60+
Boundary max;
61+
62+
/**
63+
* @return new {@link Range}
64+
*/
65+
public static Range range() {
66+
return new Range();
67+
}
68+
69+
/**
70+
* @return new {@link Range} with {@literal min} and {@literal max} set to {@link Boundary#infinite()}.
71+
*/
72+
public static Range unbounded() {
73+
74+
Range range = new Range();
75+
range.min = Boundary.infinite();
76+
range.max = Boundary.infinite();
77+
return range;
78+
}
79+
80+
/**
81+
* Greater Than Equals
82+
*
83+
* @param min
84+
* @return
85+
*/
86+
public Range gte(Object min) {
87+
88+
Assert.notNull(min, "Min already set for range.");
89+
this.min = new Boundary(min, true);
90+
return this;
91+
}
92+
93+
/**
94+
* Greater Than
95+
*
96+
* @param min
97+
* @return
98+
*/
99+
public Range gt(Object min) {
100+
101+
Assert.notNull(min, "Min already set for range.");
102+
this.min = new Boundary(min, false);
103+
return this;
104+
}
105+
106+
/**
107+
* Less Then Equals
108+
*
109+
* @param max
110+
* @return
111+
*/
112+
public Range lte(Object max) {
113+
114+
Assert.notNull(max, "Max already set for range.");
115+
this.max = new Boundary(max, true);
116+
return this;
117+
}
118+
119+
/**
120+
* Less Than
121+
*
122+
* @param max
123+
* @return
124+
*/
125+
public Range lt(Object max) {
126+
127+
Assert.notNull(max, "Max already set for range.");
128+
this.max = new Boundary(max, false);
129+
return this;
130+
}
131+
132+
/**
133+
* @return {@literal null} if not set.
134+
*/
135+
public Boundary getMin() {
136+
return min;
137+
}
138+
139+
/**
140+
* @return {@literal null} if not set.
141+
*/
142+
public Boundary getMax() {
143+
return max;
144+
}
145+
146+
/**
147+
* @author Christoph Strobl
148+
* @since 1.6
149+
*/
150+
public static class Boundary {
151+
152+
Object value;
153+
boolean including;
154+
155+
static Boundary infinite() {
156+
return new Boundary(null, true);
157+
}
158+
159+
Boundary(Object value, boolean including) {
160+
this.value = value;
161+
this.including = including;
162+
}
163+
164+
public Object getValue() {
165+
return value;
166+
}
167+
168+
public boolean isIncluding() {
169+
return including;
170+
}
171+
}
172+
173+
}
174+
175+
/**
176+
* @author Christoph Strobl
177+
* @since 1.6
178+
*/
179+
public class Limit {
180+
181+
int offset;
182+
int count;
183+
184+
public static Limit limit() {
185+
return new Limit();
186+
}
187+
188+
public Limit offset(int offset) {
189+
this.offset = offset;
190+
return this;
191+
}
192+
193+
public Limit count(int count) {
194+
this.count = count;
195+
return this;
196+
}
197+
198+
public int getCount() {
199+
return count;
200+
}
201+
202+
public int getOffset() {
203+
return offset;
204+
}
205+
206+
}
207+
50208
/**
51209
* Add {@code value} to a sorted set at {@code key}, or update its {@code score} if it already exists.
52210
* <p>
@@ -415,4 +573,36 @@ public interface Tuple extends Comparable<Double> {
415573
* @return
416574
*/
417575
Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset, long count);
576+
577+
/**
578+
* Get all the elements in the sorted set at {@literal key} in lexicographical ordering.
579+
*
580+
* @param key must not be {@literal null}.
581+
* @return
582+
* @since 1.6
583+
*/
584+
Set<byte[]> zRangeByLex(byte[] key);
585+
586+
/**
587+
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering.
588+
*
589+
* @param key must not be {@literal null}.
590+
* @param range must not be {@literal null}.
591+
* @return
592+
* @since 1.6
593+
*/
594+
Set<byte[]> zRangeByLex(byte[] key, Range range);
595+
596+
/**
597+
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is
598+
* limited via {@link Limit}.
599+
*
600+
* @param key must not be {@literal null}.
601+
* @param range must not be {@literal null}.
602+
* @param range can be {@literal null}.
603+
* @return
604+
* @since 1.6
605+
*/
606+
Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit);
607+
418608
}

src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2014 the original author or authors.
2+
* Copyright 2011-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -392,4 +392,36 @@ public interface StringTuple extends Tuple {
392392
* @since 1.5
393393
*/
394394
void pfMerge(String destinationKey, String... sourceKeys);
395+
396+
/**
397+
* Get all elements in the sorted set at {@literal key} in lexicographical ordering.
398+
*
399+
* @param key must not be {@literal null}.
400+
* @return
401+
* @since 1.6
402+
*/
403+
Set<String> zRangeByLex(String key);
404+
405+
/**
406+
* Get the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering
407+
*
408+
* @param key must not be {@literal null}.
409+
* @param range must not be {@literal null}.
410+
* @return
411+
* @since 1.6
412+
*/
413+
Set<String> zRangeByLex(String key, Range range);
414+
415+
/**
416+
* Get the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is
417+
* limited via {@link Limit}.
418+
*
419+
* @param key must not be {@literal null}.
420+
* @param range must not be {@literal null}.
421+
* @param range can be {@literal null}.
422+
* @return
423+
* @since 1.6
424+
*/
425+
Set<String> zRangeByLex(String key, Range range, Limit limit);
426+
395427
}

src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,6 +2139,61 @@ public Set<Tuple> zRangeWithScores(byte[] key, long start, long end) {
21392139
}
21402140
}
21412141

2142+
/*
2143+
* (non-Javadoc)
2144+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[])
2145+
*/
2146+
public Set<byte[]> zRangeByLex(byte[] key) {
2147+
return zRangeByLex(key, Range.unbounded());
2148+
}
2149+
2150+
/*
2151+
* (non-Javadoc)
2152+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range)
2153+
*/
2154+
public Set<byte[]> zRangeByLex(byte[] key, Range range) {
2155+
return zRangeByLex(key, range, null);
2156+
}
2157+
2158+
/*
2159+
* (non-Javadoc)
2160+
* @see org.springframework.data.redis.connection.RedisZSetCommands#zRangeByLex(byte[], org.springframework.data.redis.connection.RedisZSetCommands.Range, org.springframework.data.redis.connection.RedisZSetCommands.Limit)
2161+
*/
2162+
public Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit) {
2163+
2164+
Assert.notNull(range, "Range cannot be null for ZRANGEBYLEX.");
2165+
2166+
byte[] min = JedisConverters.boundaryToBytesForZRangeByLex(range.getMin(), JedisConverters.toBytes("-"));
2167+
byte[] max = JedisConverters.boundaryToBytesForZRangeByLex(range.getMax(), JedisConverters.toBytes("+"));
2168+
2169+
try {
2170+
if (isPipelined()) {
2171+
if (limit != null) {
2172+
pipeline(new JedisResult(pipeline.zrangeByLex(key, min, max, limit.getOffset(), limit.getCount())));
2173+
} else {
2174+
pipeline(new JedisResult(pipeline.zrangeByLex(key, min, max)));
2175+
}
2176+
return null;
2177+
}
2178+
2179+
if (isQueueing()) {
2180+
if (limit != null) {
2181+
transaction(new JedisResult(transaction.zrangeByLex(key, min, max, limit.getOffset(), limit.getCount())));
2182+
} else {
2183+
transaction(new JedisResult(transaction.zrangeByLex(key, min, max)));
2184+
}
2185+
return null;
2186+
}
2187+
2188+
if (limit != null) {
2189+
return jedis.zrangeByLex(key, min, max, limit.getOffset(), limit.getCount());
2190+
}
2191+
return jedis.zrangeByLex(key, min, max);
2192+
} catch (Exception ex) {
2193+
throw convertJedisAccessException(ex);
2194+
}
2195+
}
2196+
21422197
public Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
21432198
try {
21442199
if (isPipelined()) {

0 commit comments

Comments
 (0)