The order of elements is from the lowest to the highest score. Elements with the same score are ordered lexicographically.
The optional REV argument reverses the ordering, so elements are ordered from highest to lowest score, and score ties are resolved by reverse lexicographical ordering.
The optional LIMIT argument can be used to obtain a sub-range from the matching elements (similar to SELECT LIMIT offset, count in SQL).
A negative <count> returns all elements from the <offset>. Keep in mind that if <offset> is large, the sorted set needs to be traversed for <offset> elements before getting to the elements to return, which can add up to O(N) time complexity.
The optional WITHSCORES argument supplements the command's reply with the scores of elements returned. The returned list contains value1,score1,...,valueN,scoreN instead of value1,...,valueN. Client libraries are free to return a more appropriate data type (suggestion: an array with (value, score) arrays/tuples).
Index ranges
By default, the command performs an index range query. The <start> and <stop> arguments represent zero-based indexes, where 0 is the first element, 1 is the next element, and so on. These arguments specify an inclusive range, so for example, ZRANGE myzset 0 1 will return both the first and the second element of the sorted set.
The indexes can also be negative numbers indicating offsets from the end of the sorted set, with -1 being the last element of the sorted set, -2 the penultimate element, and so on.
Out of range indexes do not produce an error.
If <start> is greater than either the end index of the sorted set or <stop>, an empty list is returned.
If <stop> is greater than the end index of the sorted set, Redis will use the last element of the sorted set.
Score ranges
When the BYSCORE option is provided, the command behaves like ZRANGEBYSCORE and returns the range of elements from the sorted set having scores equal or between <start> and <stop>.
<start> and <stop> can be -inf and +inf, denoting the negative and positive infinities, respectively. This means that you are not required to know the highest or lowest score in the sorted set to get all elements from or up to a certain score.
By default, the score intervals specified by <start> and <stop> are closed (inclusive).
It is possible to specify an open interval (exclusive) by prefixing the score
with the character (.
For example:
ZRANGE zset (1 5 BYSCORE
Will return all elements with 1 < score <= 5 while:
ZRANGE zset (5 (10 BYSCORE
Will return all the elements with 5 < score < 10 (5 and 10 excluded).
Reverse ranges
Using the REV option reverses the sorted set, with index 0 as the element with the highest score.
By default, <start> must be less than or equal to <stop> to return anything.
However, if the BYSCORE, or BYLEX options are selected, the <start> is the highest score to consider, and <stop> is the lowest score to consider, therefore <start> must be greater than or equal to <stop> in order to return anything.
For example:
ZRANGE zset 5 10 REV
Will return the elements between index 5 and 10 in the reversed index.
ZRANGE zset 10 5 REV BYSCORE
Will return all elements with scores less than 10 and greater than 5.
Lexicographical ranges
When the BYLEX option is used, the command behaves like ZRANGEBYLEX and returns the range of elements from the sorted set between the <start> and <stop> lexicographical closed range intervals.
Note that lexicographical ordering relies on all elements having the same score. The reply is unspecified when the elements have different scores.
Valid <start> and <stop> must start with ( or [, in order to specify
whether the range interval is exclusive or inclusive, respectively.
The special values of + or - for <start> and <stop> mean positive and negative infinite strings, respectively, so for instance the command ZRANGE myzset - + BYLEX is guaranteed to return all the elements in the sorted set, providing that all the elements have the same score.
The REV options reverses the order of the <start> and <stop> elements, where <start> must be lexicographically greater than <stop> to produce a non-empty result.
Lexicographical comparison of strings
Strings are compared as a binary array of bytes. Because of how the ASCII character set is specified, this means that usually this also have the effect of comparing normal ASCII characters in an obvious dictionary way. However, this is not true if non-plain ASCII strings are used (for example, utf8 strings).
However, the user can apply a transformation to the encoded string so that the first part of the element inserted in the sorted set will compare as the user requires for the specific application. For example, if I want to
add strings that will be compared in a case-insensitive way, but I still
want to retrieve the real case when querying, I can add strings in the
following way:
ZADD autocomplete 0 foo:Foo 0 bar:BAR 0 zap:zap
Because of the first normalized part in every element (before the colon character), we are forcing a given comparison. However, after the range is queried using ZRANGE ... BYLEX, the application can display to the user the second part of the string, after the colon.
The binary nature of the comparison allows to use sorted sets as a general purpose index, for example, the first part of the element can be a 64-bit big-endian number. Since big-endian numbers have the most significant bytes in the initial positions, the binary comparison will match the numerical comparison of the numbers. This can be used in order to implement range queries on 64-bit values. As in the example below, after the first 8 bytes, we can store the value of the element we are indexing.
importjava.util.HashMap;importjava.util.Map;importjava.util.List;importredis.clients.jedis.UnifiedJedis;importredis.clients.jedis.params.ZRangeParams;importredis.clients.jedis.resps.Tuple;publicclassCmdsSortedSetExample{publicvoidrun(){UnifiedJedisjedis=newUnifiedJedis("redis://localhost:6379");// Tests for 'bzmpop' step.
// Tests for 'bzpopmax' step.
// Tests for 'bzpopmin' step.
Map<String,Double>zAddExampleParams=newHashMap<>();zAddExampleParams.put("one",1.0);longzAddResult1=jedis.zadd("myzset",zAddExampleParams);System.out.println(zAddResult1);// >>> 1
zAddExampleParams.clear();zAddExampleParams.put("uno",1.0);longzAddResult2=jedis.zadd("myzset",zAddExampleParams);System.out.println(zAddResult2);// >>> 1
zAddExampleParams.clear();zAddExampleParams.put("two",2.0);zAddExampleParams.put("three",3.0);longzAddResult3=jedis.zadd("myzset",zAddExampleParams);System.out.println(zAddResult3);// >>> 2
List<Tuple>zAddResult4=jedis.zrangeWithScores("myzset",newZRangeParams(0,-1));for(Tupleitem:zAddResult4){System.out.println("Element: "+item.getElement()+", Score: "+item.getScore());}// >>> Element: one, Score: 1.0
// >>> Element: uno, Score: 1.0
// >>> Element: two, Score: 2.0
// >>> Element: three, Score: 3.0
// Tests for 'zadd' step.
// Tests for 'zcard' step.
// Tests for 'zcount' step.
// Tests for 'zdiff' step.
// Tests for 'zdiffstore' step.
// Tests for 'zincrby' step.
// Tests for 'zinter' step.
// Tests for 'zintercard' step.
// Tests for 'zinterstore' step.
// Tests for 'zlexcount' step.
// Tests for 'zmpop' step.
// Tests for 'zmscore' step.
// Tests for 'zpopmax' step.
// Tests for 'zpopmin' step.
// Tests for 'zrandmember' step.
Map<String,Double>zRangeExampleParams1=newHashMap<>();zRangeExampleParams1.put("one",1.0);zRangeExampleParams1.put("two",2.0);zRangeExampleParams1.put("three",3.0);longzRangeResult1=jedis.zadd("myzset",zRangeExampleParams1);System.out.println(zRangeResult1);// >>> 3
List<String>zRangeResult2=jedis.zrange("myzset",newZRangeParams(0,-1));System.out.println(String.join(", ",zRangeResult2));// >>> one, two, three
List<String>zRangeResult3=jedis.zrange("myzset",newZRangeParams(2,3));System.out.println(String.join(", ",zRangeResult3));// >> three
List<String>zRangeResult4=jedis.zrange("myzset",newZRangeParams(-2,-1));System.out.println(String.join(", ",zRangeResult4));// >> two, three
// Tests for 'zrange1' step.
Map<String,Double>zRangeExampleParams2=newHashMap<>();zRangeExampleParams2.put("one",1.0);zRangeExampleParams2.put("two",2.0);zRangeExampleParams2.put("three",3.0);longzRangeResult5=jedis.zadd("myzset",zRangeExampleParams2);System.out.println(zRangeResult5);// >>> 3
List<Tuple>zRangeResult6=jedis.zrangeWithScores("myzset",newZRangeParams(0,1));for(Tupleitem:zRangeResult6){System.out.println("Element: "+item.getElement()+", Score: "+item.getScore());}// >>> Element: one, Score: 1.0
// >>> Element: two, Score: 2.0
// Tests for 'zrange2' step.
Map<String,Double>zRangeExampleParams3=newHashMap<>();zRangeExampleParams3.put("one",1.0);zRangeExampleParams3.put("two",2.0);zRangeExampleParams3.put("three",3.0);longzRangeResult7=jedis.zadd("myzset",zRangeExampleParams3);System.out.println(zRangeResult7);// >>> 3
List<String>zRangeResult8=jedis.zrangeByScore("myzset","(1","+inf",1,1);System.out.println(String.join(", ",zRangeResult8));// >>> three
// Tests for 'zrange3' step.
// Tests for 'zrangebylex' step.
// Tests for 'zrangebyscore' step.
// Tests for 'zrangestore' step.
// Tests for 'zrank' step.
// Tests for 'zrem' step.
// Tests for 'zremrangebylex' step.
// Tests for 'zremrangebyrank' step.
// Tests for 'zremrangebyscore' step.
// Tests for 'zrevrange' step.
// Tests for 'zrevrangebylex' step.
// Tests for 'zrevrangebyscore' step.
// Tests for 'zrevrank' step.
// Tests for 'zscan' step.
// Tests for 'zscore' step.
// Tests for 'zunion' step.
// Tests for 'zunionstore' step.
}}
packageexample_commands_testimport("context""fmt""github.com/redis/go-redis/v9")funcExampleClient_zadd_cmd(){ctx:=context.Background()rdb:=redis.NewClient(&redis.Options{Addr:"localhost:6379",Password:"",// no password docs
DB:0,// use default DB
})zAddResult1,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"one",Score:1},).Result()iferr!=nil{panic(err)}fmt.Println(zAddResult1)// >>> 1
zAddResult2,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"uno",Score:1},).Result()iferr!=nil{panic(err)}fmt.Println(zAddResult2)zAddResult3,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"two",Score:2},redis.Z{Member:"three",Score:3},).Result()iferr!=nil{panic(err)}fmt.Println(zAddResult3)// >>> 2
zAddResult4,err:=rdb.ZRangeWithScores(ctx,"myzset",0,-1).Result()iferr!=nil{panic(err)}fmt.Println(zAddResult4)// >>> [{1 one} {1 uno} {2 two} {3 three}]
}funcExampleClient_zrange1(){ctx:=context.Background()rdb:=redis.NewClient(&redis.Options{Addr:"localhost:6379",Password:"",// no password docs
DB:0,// use default DB
})zrangeResult1,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"one",Score:1},redis.Z{Member:"two",Score:2},redis.Z{Member:"three",Score:3},).Result()iferr!=nil{panic(err)}fmt.Println(zrangeResult1)// >>> 3
zrangeResult2,err:=rdb.ZRange(ctx,"myzset",0,-1).Result()iferr!=nil{panic(err)}fmt.Println(zrangeResult2)// >>> [one two three]
zrangeResult3,err:=rdb.ZRange(ctx,"myzset",2,3).Result()iferr!=nil{panic(err)}fmt.Println(zrangeResult3)// >>> [three]
zrangeResult4,err:=rdb.ZRange(ctx,"myzset",-2,-1).Result()iferr!=nil{panic(err)}fmt.Println(zrangeResult4)// >>> [two three]
}funcExampleClient_zrange2(){ctx:=context.Background()rdb:=redis.NewClient(&redis.Options{Addr:"localhost:6379",Password:"",// no password docs
DB:0,// use default DB
})zRangeResult5,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"one",Score:1},redis.Z{Member:"two",Score:2},redis.Z{Member:"three",Score:3},).Result()iferr!=nil{panic(err)}fmt.Println(zRangeResult5)// >>> 3
zRangeResult6,err:=rdb.ZRangeWithScores(ctx,"myzset",0,1).Result()iferr!=nil{panic(err)}fmt.Println(zRangeResult6)// >>> [{1 one} {2 two}]
}funcExampleClient_zrange3(){ctx:=context.Background()rdb:=redis.NewClient(&redis.Options{Addr:"localhost:6379",Password:"",// no password docs
DB:0,// use default DB
})zRangeResult7,err:=rdb.ZAdd(ctx,"myzset",redis.Z{Member:"one",Score:1},redis.Z{Member:"two",Score:2},redis.Z{Member:"three",Score:3},).Result()iferr!=nil{panic(err)}fmt.Println(zRangeResult7)// >>> 3
zRangeResult8,err:=rdb.ZRangeArgs(ctx,redis.ZRangeArgs{Key:"myzset",ByScore:true,Start:"(1",Stop:"+inf",Offset:1,Count:1,},).Result()iferr!=nil{panic(err)}fmt.Println(zRangeResult8)// >>> [three]
}
usingNRedisStack.Tests;usingStackExchange.Redis;publicclassCmdsSortedSet{publicvoidrun(){varmuxer=ConnectionMultiplexer.Connect("localhost:6379");vardb=muxer.GetDatabase();// Tests for 'bzmpop' step.// Tests for 'bzpopmax' step.// Tests for 'bzpopmin' step.boolzAddResult1=db.SortedSetAdd("myzset","one",1);Console.WriteLine(zAddResult1);// >>> TrueboolzAddResult2=db.SortedSetAdd("myzset","uno",1);Console.WriteLine(zAddResult2);// >>> TruelongzAddResult3=db.SortedSetAdd("myzset",newSortedSetEntry[]{newSortedSetEntry("two",2),newSortedSetEntry("three",3)});Console.WriteLine(zAddResult3);// >>> 2SortedSetEntry[]zAddResult4=db.SortedSetRangeByRankWithScores("myzset",0,-1);Console.WriteLine($"{string.Join(",", zAddResult4.Select(b => $"{b.Element}:{b.Score}"))}");// >>> one: 1, uno: 1, two: 2, three: 3// Tests for 'zadd' step.// Tests for 'zcard' step.// Tests for 'zcount' step.// Tests for 'zdiff' step.// Tests for 'zdiffstore' step.// Tests for 'zincrby' step.// Tests for 'zinter' step.// Tests for 'zintercard' step.// Tests for 'zinterstore' step.// Tests for 'zlexcount' step.// Tests for 'zmpop' step.// Tests for 'zmscore' step.// Tests for 'zpopmax' step.// Tests for 'zpopmin' step.// Tests for 'zrandmember' step.longzRangeResult1=db.SortedSetAdd("myzset",newSortedSetEntry[]{newSortedSetEntry("one",1),newSortedSetEntry("two",2),newSortedSetEntry("three",3)});Console.WriteLine(zRangeResult1);// >>> 3RedisValue[]zRangeResult2=db.SortedSetRangeByRank("myzset",0,-1);Console.WriteLine(string.Join(", ",zRangeResult2));// >>> one, two, threeRedisValue[]zRangeResult3=db.SortedSetRangeByRank("myzset",2,3);Console.WriteLine(string.Join(", ",zRangeResult3));// >>> threeRedisValue[]zRangeResult4=db.SortedSetRangeByRank("myzset",-2,-1);Console.WriteLine(string.Join(", ",zRangeResult4));// >>> two, three// Tests for 'zrange1' step.longzRangeResult5=db.SortedSetAdd("myzset",newSortedSetEntry[]{newSortedSetEntry("one",1),newSortedSetEntry("two",2),newSortedSetEntry("three",3)});SortedSetEntry[]zRangeResult6=db.SortedSetRangeByRankWithScores("myzset",0,1);Console.WriteLine($"{string.Join(",", zRangeResult6.Select(b => $"{b.Element}:{b.Score}"))}");// >>> one: 1, two: 2// Tests for 'zrange2' step.longzRangeResult7=db.SortedSetAdd("myzset",newSortedSetEntry[]{newSortedSetEntry("one",1),newSortedSetEntry("two",2),newSortedSetEntry("three",3)});RedisValue[]zRangeResult8=db.SortedSetRangeByScore("myzset",1,double.PositiveInfinity,Exclude.Start,skip:1,take:1);Console.WriteLine(string.Join(", ",zRangeResult8));// >>> three// Tests for 'zrange3' step.// Tests for 'zrangebylex' step.// Tests for 'zrangebyscore' step.// Tests for 'zrangestore' step.// Tests for 'zrank' step.// Tests for 'zrem' step.// Tests for 'zremrangebylex' step.// Tests for 'zremrangebyrank' step.// Tests for 'zremrangebyscore' step.// Tests for 'zrevrange' step.// Tests for 'zrevrangebylex' step.// Tests for 'zrevrangebyscore' step.// Tests for 'zrevrank' step.// Tests for 'zscan' step.// Tests for 'zscore' step.// Tests for 'zunion' step.// Tests for 'zunionstore' step.}}
The following example using WITHSCORES shows how the command returns always an array, but this time, populated with element_1, score_1, element_2, score_2, ..., element_N, score_N.