/*
* Copyright 2011-2017 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.
* 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.springframework.data.redis.connection;
import java.util.Set;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.util.Assert;
/**
* ZSet(SortedSet)-specific commands supported by Redis.
*
* @author Costin Leau
* @author Christoph Strobl
* @author Thomas Darimont
* @author David Liu
* @author Mark Paluch
*/
public interface RedisZSetCommands {
/**
* Sort aggregation operations.
*/
enum Aggregate {
SUM, MIN, MAX;
}
/**
* ZSet tuple.
*/
interface Tuple extends Comparable<Double> {
byte[] getValue();
Double getScore();
}
/**
* {@link Range} defines {@literal min} and {@literal max} values to retrieve from a {@literal ZSET}.
*
* @author Christoph Strobl
* @since 1.6
*/
class Range {
Boundary min;
Boundary max;
/**
* @return new {@link Range}
*/
public static Range range() {
return new Range();
}
/**
* @return new {@link Range} with {@literal min} and {@literal max} set to {@link Boundary#infinite()}.
*/
public static Range unbounded() {
Range range = new Range();
range.min = Boundary.infinite();
range.max = Boundary.infinite();
return range;
}
/**
* Greater Than Equals
*
* @param min
* @return
*/
public Range gte(Object min) {
Assert.notNull(min, "Min already set for range.");
this.min = new Boundary(min, true);
return this;
}
/**
* Greater Than
*
* @param min
* @return
*/
public Range gt(Object min) {
Assert.notNull(min, "Min already set for range.");
this.min = new Boundary(min, false);
return this;
}
/**
* Less Then Equals
*
* @param max
* @return
*/
public Range lte(Object max) {
Assert.notNull(max, "Max already set for range.");
this.max = new Boundary(max, true);
return this;
}
/**
* Less Than
*
* @param max
* @return
*/
public Range lt(Object max) {
Assert.notNull(max, "Max already set for range.");
this.max = new Boundary(max, false);
return this;
}
/**
* @return {@literal null} if not set.
*/
public Boundary getMin() {
return min;
}
/**
* @return {@literal null} if not set.
*/
public Boundary getMax() {
return max;
}
/**
* @author Christoph Strobl
* @since 1.6
*/
public static class Boundary {
Object value;
boolean including;
static Boundary infinite() {
return new Boundary(null, true);
}
Boundary(Object value, boolean including) {
this.value = value;
this.including = including;
}
public Object getValue() {
return value;
}
public boolean isIncluding() {
return including;
}
}
}
/**
* @author Christoph Strobl
* @since 1.6
*/
class Limit {
int offset;
int count;
public static Limit limit() {
return new Limit();
}
public Limit offset(int offset) {
this.offset = offset;
return this;
}
public Limit count(int count) {
this.count = count;
return this;
}
public int getCount() {
return count;
}
public int getOffset() {
return offset;
}
}
/**
* Add {@code value} to a sorted set at {@code key}, or update its {@code score} if it already exists.
*
* @param key must not be {@literal null}.
* @param score the score.
* @param value the value.
* @return
* @see <a href="http://redis.io/commands/zadd">Redis Documentation: ZADD</a>
*/
Boolean zAdd(byte[] key, double score, byte[] value);
/**
* Add {@code tuples} to a sorted set at {@code key}, or update its {@code score} if it already exists.
*
* @param key must not be {@literal null}.
* @param tuples must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zadd">Redis Documentation: ZADD</a>
*/
Long zAdd(byte[] key, Set<Tuple> tuples);
/**
* Remove {@code values} from sorted set. Return number of removed elements.
*
* @param key must not be {@literal null}.
* @param values must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zrem">Redis Documentation: ZREM</a>
*/
Long zRem(byte[] key, byte[]... values);
/**
* Increment the score of element with {@code value} in sorted set by {@code increment}.
*
* @param key must not be {@literal null}.
* @param increment
* @param value the value.
* @return
* @see <a href="http://redis.io/commands/zincrby">Redis Documentation: ZINCRBY</a>
*/
Double zIncrBy(byte[] key, double increment, byte[] value);
/**
* Determine the index of element with {@code value} in a sorted set.
*
* @param key must not be {@literal null}.
* @param value the value.
* @return
* @see <a href="http://redis.io/commands/zrank">Redis Documentation: ZRANK</a>
*/
Long zRank(byte[] key, byte[] value);
/**
* Determine the index of element with {@code value} in a sorted set when scored high to low.
*
* @param key must not be {@literal null}.
* @param value the value.
* @return
* @see <a href="http://redis.io/commands/zrevrank">Redis Documentation: ZREVRANK</a>
*/
Long zRevRank(byte[] key, byte[] value);
/**
* Get elements between {@code start} and {@code end} from sorted set.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see <a href="http://redis.io/commands/zrange">Redis Documentation: ZRANGE</a>
*/
Set<byte[]> zRange(byte[] key, long start, long end);
/**
* Get set of {@link Tuple}s between {@code start} and {@code end} from sorted set.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see <a href="http://redis.io/commands/zrange">Redis Documentation: ZRANGE</a>
*/
Set<Tuple> zRangeWithScores(byte[] key, long start, long end);
/**
* Get elements where score is between {@code min} and {@code max} from sorted set.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
return zRangeByScore(key, new Range().gte(min).lte(max));
}
/**
* Get set of {@link Tuple}s where score is between {@code Range#min} and {@code Range#max} from sorted set.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range) {
return zRangeByScoreWithScores(key, range, null);
}
/**
* Get set of {@link Tuple}s where score is between {@code min} and {@code max} from sorted set.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max) {
return zRangeByScoreWithScores(key, new Range().gte(min).lte(max));
}
/**
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
* sorted set.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @param offset
* @param count
* @return
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<byte[]> zRangeByScore(byte[] key, double min, double max, long offset, long count) {
return zRangeByScore(key, new Range().gte(min).lte(max),
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
}
/**
* Get set of {@link Tuple}s in range from {@code start} to {@code end} where score is between {@code min} and
* {@code max} from sorted set.
*
* @param key
* @param min
* @param max
* @param offset
* @param count
* @return
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<Tuple> zRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
return zRangeByScoreWithScores(key, new Range().gte(min).lte(max),
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
}
/**
* Get set of {@link Tuple}s in range from {@code Limit#offset} to {@code Limit#offset + Limit#count} where score is
* between {@code Range#min} and {@code Range#max} from sorted set.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @param limit
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
Set<Tuple> zRangeByScoreWithScores(byte[] key, Range range, Limit limit);
/**
* Get elements in range from {@code start} to {@code end} from sorted set ordered from high to low.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see <a href="http://redis.io/commands/zrevrange">Redis Documentation: ZREVRANGE</a>
*/
Set<byte[]> zRevRange(byte[] key, long start, long end);
/**
* Get set of {@link Tuple}s in range from {@code start} to {@code end} from sorted set ordered from high to low.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see <a href="http://redis.io/commands/zrevrange">Redis Documentation: ZREVRANGE</a>
*/
Set<Tuple> zRevRangeWithScores(byte[] key, long start, long end);
/**
* Get elements where score is between {@code min} and {@code max} from sorted set ordered from high to low.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zrevrange">Redis Documentation: ZREVRANGE</a>
*/
default Set<byte[]> zRevRangeByScore(byte[] key, double min, double max) {
return zRevRangeByScore(key, new Range().gte(min).lte(max));
}
/**
* Get elements where score is between {@code Range#min} and {@code Range#max} from sorted set ordered from high to
* low.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
default Set<byte[]> zRevRangeByScore(byte[] key, Range range) {
return zRevRangeByScore(key, range, null);
}
/**
* Get set of {@link Tuple} where score is between {@code min} and {@code max} from sorted set ordered from high to
* low.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max) {
return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max), null);
}
/**
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
* sorted set ordered high -> low.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @param offset
* @param count
* @return
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
default Set<byte[]> zRevRangeByScore(byte[] key, double min, double max, long offset, long count) {
return zRevRangeByScore(key, new Range().gte(min).lte(max),
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
}
/**
* Get elements in range from {@code Limit#offset} to {@code Limit#offset + Limit#count} where score is between
* {@code Range#min} and {@code Range#max} from sorted set ordered high -> low.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @param limit
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
Set<byte[]> zRevRangeByScore(byte[] key, Range range, Limit limit);
/**
* Get set of {@link Tuple} in range from {@code start} to {@code end} where score is between {@code min} and
* {@code max} from sorted set ordered high -> low.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @param offset
* @param count
* @return
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, double min, double max, long offset, long count) {
return zRevRangeByScoreWithScores(key, new Range().gte(min).lte(max),
new Limit().offset(Long.valueOf(offset).intValue()).count(Long.valueOf(count).intValue()));
}
/**
* Get set of {@link Tuple} where score is between {@code Range#min} and {@code Range#max} from sorted set ordered
* from high to low.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
default Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range) {
return zRevRangeByScoreWithScores(key, range, null);
}
/**
* Get set of {@link Tuple} in range from {@code Limit#offset} to {@code Limit#count} where score is between
* {@code Range#min} and {@code Range#max} from sorted set ordered high -> low.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @param limit
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrevrangebyscore">Redis Documentation: ZREVRANGEBYSCORE</a>
*/
Set<Tuple> zRevRangeByScoreWithScores(byte[] key, Range range, Limit limit);
/**
* Count number of elements within sorted set with scores between {@code min} and {@code max}.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zcount">Redis Documentation: ZCOUNT</a>
*/
default Long zCount(byte[] key, double min, double max) {
return zCount(key, new Range().gte(min).lte(max));
}
/**
* Count number of elements within sorted set with scores between {@code Range#min} and {@code Range#max}.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zcount">Redis Documentation: ZCOUNT</a>
*/
Long zCount(byte[] key, Range range);
/**
* Get the size of sorted set with {@code key}.
*
* @param key must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zcard">Redis Documentation: ZCARD</a>
*/
Long zCard(byte[] key);
/**
* Get the score of element with {@code value} from sorted set with key {@code key}.
*
* @param key must not be {@literal null}.
* @param value the value.
* @return
* @see <a href="http://redis.io/commands/zrem">Redis Documentation: ZREM</a>
*/
Double zScore(byte[] key, byte[] value);
/**
* Remove elements in range between {@code start} and {@code end} from sorted set with {@code key}.
*
* @param key must not be {@literal null}.
* @param start
* @param end
* @return
* @see <a href="http://redis.io/commands/zremrangebyrank">Redis Documentation: ZREMRANGEBYRANK</a>
*/
Long zRemRange(byte[] key, long start, long end);
/**
* Remove elements with scores between {@code min} and {@code max} from sorted set with {@code key}.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @see <a href="http://redis.io/commands/zremrangebyscore">Redis Documentation: ZREMRANGEBYSCORE</a>
*/
default Long zRemRangeByScore(byte[] key, double min, double max) {
return zRemRangeByScore(key, new Range().gte(min).lte(max));
}
/**
* Remove elements with scores between {@code Range#min} and {@code Range#max} from sorted set with {@code key}.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zremrangebyscore">Redis Documentation: ZREMRANGEBYSCORE</a>
*/
Long zRemRangeByScore(byte[] key, Range range);
/**
* Union sorted {@code sets} and store result in destination {@code key}.
*
* @param destKey must not be {@literal null}.
* @param sets must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zunionstore">Redis Documentation: ZUNIONSTORE</a>
*/
Long zUnionStore(byte[] destKey, byte[]... sets);
/**
* Union sorted {@code sets} and store result in destination {@code key}.
*
* @param destKey must not be {@literal null}.
* @param aggregate must not be {@literal null}.
* @param weights
* @param sets must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zunionstore">Redis Documentation: ZUNIONSTORE</a>
*/
Long zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets);
/**
* Intersect sorted {@code sets} and store result in destination {@code key}.
*
* @param destKey must not be {@literal null}.
* @param sets must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
*/
Long zInterStore(byte[] destKey, byte[]... sets);
/**
* Intersect sorted {@code sets} and store result in destination {@code key}.
*
* @param destKey must not be {@literal null}.
* @param aggregate must not be {@literal null}.
* @param weights
* @param sets must not be {@literal null}.
* @return
* @see <a href="http://redis.io/commands/zinterstore">Redis Documentation: ZINTERSTORE</a>
*/
Long zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets);
/**
* Use a {@link Cursor} to iterate over elements in sorted set at {@code key}.
*
* @param key must not be {@literal null}.
* @param options must not be {@literal null}.
* @return
* @since 1.4
* @see <a href="http://redis.io/commands/zscan">Redis Documentation: ZSCAN</a>
*/
Cursor<Tuple> zScan(byte[] key, ScanOptions options);
/**
* Get elements where score is between {@code min} and {@code max} from sorted set.
*
* @param key must not be {@literal null}.
* @param min
* @param max
* @return
* @since 1.5
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<byte[]> zRangeByScore(byte[] key, String min, String max) {
return zRangeByScore(key, new Range().gte(min).lte(max));
}
/**
* Get elements where score is between {@code Range#min} and {@code Range#max} from sorted set.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
default Set<byte[]> zRangeByScore(byte[] key, Range range) {
return zRangeByScore(key, range, null);
}
/**
* Get elements in range from {@code start} to {@code end} where score is between {@code min} and {@code max} from
* sorted set.
*
* @param key must not be {@literal null}.
* @param min must not be {@literal null}.
* @param max must not be {@literal null}.
* @param offset
* @param count
* @return
* @since 1.5
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
Set<byte[]> zRangeByScore(byte[] key, String min, String max, long offset, long count);
/**
* Get elements in range from {@code Limit#count} to {@code Limit#offset} where score is between {@code Range#min} and
* {@code Range#max} from sorted set.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @param limit
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebyscore">Redis Documentation: ZRANGEBYSCORE</a>
*/
Set<byte[]> zRangeByScore(byte[] key, Range range, Limit limit);
/**
* Get all the elements in the sorted set at {@literal key} in lexicographical ordering.
*
* @param key must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebylex">Redis Documentation: ZRANGEBYLEX</a>
*/
default Set<byte[]> zRangeByLex(byte[] key) {
return zRangeByLex(key, Range.unbounded());
}
/**
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebylex">Redis Documentation: ZRANGEBYLEX</a>
*/
default Set<byte[]> zRangeByLex(byte[] key, Range range) {
return zRangeByLex(key, range, null);
}
/**
* Get all the elements in {@link Range} from the sorted set at {@literal key} in lexicographical ordering. Result is
* limited via {@link Limit}.
*
* @param key must not be {@literal null}.
* @param range must not be {@literal null}.
* @param range can be {@literal null}.
* @return
* @since 1.6
* @see <a href="http://redis.io/commands/zrangebylex">Redis Documentation: ZRANGEBYLEX</a>
*/
Set<byte[]> zRangeByLex(byte[] key, Range range, Limit limit);
}