ZADD
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member ...]
- Available since:
- Redis Open Source 1.2.0
- Time complexity:
- O(log(N)) for each item added, where N is the number of elements in the sorted set.
- ACL categories:
-
@write,@sortedset,@fast, - Compatibility:
- Redis Software and Redis Cloud compatibility
Adds all the specified members with the specified scores to the sorted set
stored at key.
It is possible to specify multiple score / member pairs.
If a specified member is already a member of the sorted set, the score is
updated and the element reinserted at the right position to ensure the correct
ordering.
If key does not exist, a new sorted set with the specified members as sole
members is created, like if the sorted set was empty. If the key exists but does not hold a sorted set, an error is returned.
The score values should be the string representation of a double precision floating point number. +inf and -inf values are valid values as well.
Required arguments
key
The name of the key that holds the sorted set.
score member [score member ...]
One or more score-member pairs to add or update. score is a double-precision floating-point number.
Optional arguments
NX and XX are mutually exclusive, as are GT and LT.
NX
Only add new members; do not update existing members.
XX
Only update existing members; do not add new members.
GT
Only update an existing member if the new score is greater than the current score. Does not prevent adding new members.
LT
Only update an existing member if the new score is less than the current score. Does not prevent adding new members.
CH
Change the return value from the number of added members to the number of changed members (added plus updated).
INCR
Increment the member's score by score instead of setting it, behaving like ZINCRBY. Only one score-member pair may be given.
Examples
> ZADD myzset 1 "one"
(integer) 1
> ZADD myzset 1 "uno"
(integer) 1
> ZADD myzset 2 "two" 3 "three"
(integer) 2
> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"res = r.zadd("myzset", {"one": 1})
print(res)
# >>> 1
res = r.zadd("myzset", {"uno": 1})
print(res)
# >>> 1
res = r.zadd("myzset", {"two": 2, "three": 3})
print(res)
# >>> 2
res = r.zrange("myzset", 0, -1, withscores=True)
# >>> [('one', 1.0), ('uno', 1.0), ('two', 2.0), ('three', 3.0)]
import redis
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
res = r.zadd("myzset", {"one": 1})
print(res)
# >>> 1
res = r.zadd("myzset", {"uno": 1})
print(res)
# >>> 1
res = r.zadd("myzset", {"two": 2, "three": 3})
print(res)
# >>> 2
res = r.zrange("myzset", 0, -1, withscores=True)
# >>> [('one', 1.0), ('uno', 1.0), ('two', 2.0), ('three', 3.0)]
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
print(res)
# >>> 3
res = r.zrange("myzset", 0, -1)
print(res)
# >>> ['one', 'two', 'three']
res = r.zrange("myzset", 2, 3)
print(res)
# >>> ['three']
res = r.zrange("myzset", -2, -1)
print(res)
# >>> ['two', 'three']
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
res = r.zrange("myzset", 0, 1, withscores=True)
print(res)
# >>> [('one', 1.0), ('two', 2.0)]
res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
res = r.zrange("myzset", 2, 3, byscore=True, offset=1, num=1)
print(res)
# >>> ['three']
const val1 = await client.zAdd("myzset", [{ value: 'one', score: 1 }]);
console.log(val1);
// returns 1
const val2 = await client.zAdd("myzset", [{ value: 'uno', score: 1 }]);
console.log(val2);
// returns 1
const val3 = await client.zAdd("myzset", [{ value: 'two', score: 2 }, { value: 'three', score: 3 }]);
console.log(val3);
// returns 2
const val4 = await client.zRangeWithScores("myzset", 0, -1);
console.log(val4);
// returns [{value: 'one', score: 1}, {value: 'uno', score: 1}, {value: 'two', score: 2}, {value: 'three', score: 3} ]
import { createClient } from 'redis';
const client = createClient();
client.on('error', err => console.log('Redis Client Error', err));
await client.connect().catch(console.error);
const val1 = await client.zAdd("myzset", [{ value: 'one', score: 1 }]);
console.log(val1);
// returns 1
const val2 = await client.zAdd("myzset", [{ value: 'uno', score: 1 }]);
console.log(val2);
// returns 1
const val3 = await client.zAdd("myzset", [{ value: 'two', score: 2 }, { value: 'three', score: 3 }]);
console.log(val3);
// returns 2
const val4 = await client.zRangeWithScores("myzset", 0, -1);
console.log(val4);
// returns [{value: 'one', score: 1}, {value: 'uno', score: 1}, {value: 'two', score: 2}, {value: 'three', score: 3} ]
const val5 = await client.zAdd("myzset", [
{ value: 'one', score: 1 },
{ value: 'two', score: 2 },
{ value: 'three', score: 3 }
]);
console.log(val5);
// returns 3
const val6 = await client.zRange('myzset', 0, -1);
console.log(val6);
// returns ['one', 'two', 'three']
const val7 = await client.zRange('myzset', 2, 3);
console.log(val7);
// returns ['three']
const val8 = await client.zRange('myzset', -2, -1);
console.log(val8);
// returns ['two', 'three']
const val9 = await client.zAdd("myzset", [
{ value: 'one', score: 1 },
{ value: 'two', score: 2 },
{ value: 'three', score: 3 }
]);
console.log(val9);
// returns 3
const val10 = await client.zRangeWithScores('myzset', 0, 1);
console.log(val10);
// returns [{value: 'one', score: 1}, {value: 'two', score: 2}]
const val11 = await client.zAdd("myzset", [
{ value: 'one', score: 1 },
{ value: 'two', score: 2 },
{ value: 'three', score: 3 }
]);
console.log(val11);
// returns 3
const val12 = await client.zRange('myzset', 2, 3, { BY: 'SCORE', LIMIT: { offset: 1, count: 1 } });
console.log(val12);
// >>> ['three']
await client.close();
Map<String, Double> zAddExampleParams = new HashMap<>();
zAddExampleParams.put("one", 1.0);
long zAddResult1 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult1); // >>> 1
zAddExampleParams.clear();
zAddExampleParams.put("uno", 1.0);
long zAddResult2 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult2); // >>> 1
zAddExampleParams.clear();
zAddExampleParams.put("two", 2.0);
zAddExampleParams.put("three", 3.0);
long zAddResult3 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult3); // >>> 2
List<Tuple> zAddResult4 = jedis.zrangeWithScores("myzset", new ZRangeParams(0, -1));
for (Tuple item: 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
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import redis.clients.jedis.RedisClient;
import redis.clients.jedis.params.ZRangeParams;
import redis.clients.jedis.resps.Tuple;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CmdsSortedSetExample {
public void run() {
RedisClient jedis = RedisClient.create("redis://localhost:6379");
// Tests for 'bzmpop' step.
// Tests for 'bzpopmax' step.
// Tests for 'bzpopmin' step.
Map<String, Double> zAddExampleParams = new HashMap<>();
zAddExampleParams.put("one", 1.0);
long zAddResult1 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult1); // >>> 1
zAddExampleParams.clear();
zAddExampleParams.put("uno", 1.0);
long zAddResult2 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult2); // >>> 1
zAddExampleParams.clear();
zAddExampleParams.put("two", 2.0);
zAddExampleParams.put("three", 3.0);
long zAddResult3 = jedis.zadd("myzset", zAddExampleParams);
System.out.println(zAddResult3); // >>> 2
List<Tuple> zAddResult4 = jedis.zrangeWithScores("myzset", new ZRangeParams(0, -1));
for (Tuple item: 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 = new HashMap<>();
zRangeExampleParams1.put("one", 1.0);
zRangeExampleParams1.put("two", 2.0);
zRangeExampleParams1.put("three", 3.0);
long zRangeResult1 = jedis.zadd("myzset", zRangeExampleParams1);
System.out.println(zRangeResult1); // >>> 3
List<String> zRangeResult2 = jedis.zrange("myzset", new ZRangeParams(0, -1));
System.out.println(String.join(", ", zRangeResult2)); // >>> one, two, three
List<String> zRangeResult3 = jedis.zrange("myzset", new ZRangeParams(2, 3));
System.out.println(String.join(", ", zRangeResult3)); // >> three
List<String> zRangeResult4 = jedis.zrange("myzset", new ZRangeParams(-2, -1));
System.out.println(String.join(", ", zRangeResult4)); // >> two, three
// Tests for 'zrange1' step.
Map<String, Double> zRangeExampleParams2 = new HashMap<>();
zRangeExampleParams2.put("one", 1.0);
zRangeExampleParams2.put("two", 2.0);
zRangeExampleParams2.put("three", 3.0);
long zRangeResult5 = jedis.zadd("myzset", zRangeExampleParams2);
System.out.println(zRangeResult5); // >>> 3
List<Tuple> zRangeResult6 = jedis.zrangeWithScores("myzset", new ZRangeParams(0, 1));
for (Tuple item: 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 = new HashMap<>();
zRangeExampleParams3.put("one", 1.0);
zRangeExampleParams3.put("two", 2.0);
zRangeExampleParams3.put("three", 3.0);
long zRangeResult7 = 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.
jedis.close();
}
}
zAddResult1, err := rdb.ZAdd(ctx, "myzset",
redis.Z{Member: "one", Score: 1},
).Result()
if err != nil {
panic(err)
}
fmt.Println(zAddResult1) // >>> 1
zAddResult2, err := rdb.ZAdd(ctx, "myzset",
redis.Z{Member: "uno", Score: 1},
).Result()
if err != 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()
if err != nil {
panic(err)
}
fmt.Println(zAddResult3) // >>> 2
zAddResult4, err := rdb.ZRangeWithScores(ctx, "myzset", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(zAddResult4) // >>> [{1 one} {1 uno} {2 two} {3 three}]
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleClient_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()
if err != nil {
panic(err)
}
fmt.Println(zAddResult1) // >>> 1
zAddResult2, err := rdb.ZAdd(ctx, "myzset",
redis.Z{Member: "uno", Score: 1},
).Result()
if err != 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()
if err != nil {
panic(err)
}
fmt.Println(zAddResult3) // >>> 2
zAddResult4, err := rdb.ZRangeWithScores(ctx, "myzset", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(zAddResult4) // >>> [{1 one} {1 uno} {2 two} {3 three}]
}
func ExampleClient_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()
if err != nil {
panic(err)
}
fmt.Println(zrangeResult1) // >>> 3
zrangeResult2, err := rdb.ZRange(ctx, "myzset", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(zrangeResult2) // >>> [one two three]
zrangeResult3, err := rdb.ZRange(ctx, "myzset", 2, 3).Result()
if err != nil {
panic(err)
}
fmt.Println(zrangeResult3) // >>> [three]
zrangeResult4, err := rdb.ZRange(ctx, "myzset", -2, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(zrangeResult4) // >>> [two three]
}
func ExampleClient_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()
if err != nil {
panic(err)
}
fmt.Println(zRangeResult5) // >>> 3
zRangeResult6, err := rdb.ZRangeWithScores(ctx, "myzset", 0, 1).Result()
if err != nil {
panic(err)
}
fmt.Println(zRangeResult6) // >>> [{1 one} {2 two}]
}
func ExampleClient_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()
if err != 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()
if err != nil {
panic(err)
}
fmt.Println(zRangeResult8) // >>> [three]
}
bool zAddResult1 = db.SortedSetAdd("myzset", "one", 1);
Console.WriteLine(zAddResult1); // >>> True
bool zAddResult2 = db.SortedSetAdd("myzset", "uno", 1);
Console.WriteLine(zAddResult2); // >>> True
long zAddResult3 = db.SortedSetAdd(
"myzset",
[
new("two", 2),
new("three", 3)
]
);
Console.WriteLine(zAddResult3); // >>> 2
SortedSetEntry[] 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
using NRedisStack.Tests;
using StackExchange.Redis;
public class CmdsSortedSet
{
public void Run()
{
var muxer = ConnectionMultiplexer.Connect("localhost:6379");
var db = muxer.GetDatabase();
// Tests for 'bzmpop' step.
// Tests for 'bzpopmax' step.
// Tests for 'bzpopmin' step.
bool zAddResult1 = db.SortedSetAdd("myzset", "one", 1);
Console.WriteLine(zAddResult1); // >>> True
bool zAddResult2 = db.SortedSetAdd("myzset", "uno", 1);
Console.WriteLine(zAddResult2); // >>> True
long zAddResult3 = db.SortedSetAdd(
"myzset",
[
new("two", 2),
new("three", 3)
]
);
Console.WriteLine(zAddResult3); // >>> 2
SortedSetEntry[] 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.
long zRangeResult1 = db.SortedSetAdd(
"myzset",
[
new("one", 1),
new("two", 2),
new("three", 3)
]
);
Console.WriteLine(zRangeResult1); // >>> 3
RedisValue[] zRangeResult2 = db.SortedSetRangeByRank("myzset", 0, -1);
Console.WriteLine(string.Join(", ", zRangeResult2));
// >>> one, two, three
RedisValue[] zRangeResult3 = db.SortedSetRangeByRank("myzset", 2, 3);
Console.WriteLine(string.Join(", ", zRangeResult3));
// >>> three
RedisValue[] zRangeResult4 = db.SortedSetRangeByRank("myzset", -2, -1);
Console.WriteLine(string.Join(", ", zRangeResult4));
// >>> two, three
// Tests for 'zrange1' step.
long zRangeResult5 = db.SortedSetAdd(
"myzset",
[
new("one", 1),
new("two", 2),
new("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.
long zRangeResult7 = db.SortedSetAdd(
"myzset",
[
new("one", 1),
new("two", 2),
new("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.
}
}
Give these commands a try in the interactive console:
Details
Range of integer scores that can be expressed precisely
Redis sorted sets use a double 64-bit floating-point number to represent the score. This format precisely represents integers between -(2^53) and +(2^53), inclusive. In practical terms, you can store integers from -9007199254740992 to 9007199254740992 without losing precision. Redis represents larger integers and fractions in exponential form internally, so you may get only an approximation of the score you set.
Sorted sets 101
Sorted sets are sorted by their score in an ascending way.
The same element only exists a single time, no repeated elements are
permitted. The score can be modified both by ZADD that will update the
element score, and as a side effect, its position on the sorted set, and
by ZINCRBY that can be used in order to update the score relatively to its
previous value.
The current score of an element can be retrieved using the ZSCORE command,
that can also be used to verify if an element already exists or not.
For an introduction to sorted sets, see the data types page on sorted sets.
Elements with the same score
While the same element can't be repeated in a sorted set since every element is unique, it is possible to add multiple different elements having the same score. When multiple elements have the same score, they are ordered lexicographically (they are still ordered by score as a first key, however, locally, all the elements with the same score are relatively ordered lexicographically).
The lexicographic ordering used is binary, it compares strings as array of bytes.
If the user inserts all the elements in a sorted set with the same score (for example 0), all the elements of the sorted set are sorted lexicographically, and range queries on elements are possible using the command ZRANGEBYLEX (Note: it is also possible to query sorted sets by range of scores using ZRANGEBYSCORE).
Redis Software and Redis Cloud compatibility
| Redis Software |
Redis Cloud |
Notes |
|---|---|---|
| ✅ Standard |
✅ Standard |
Return information
Any of the following:
- Nil reply: if the operation was aborted because of a conflict with one of the XX/NX/LT/GT options.
- Integer reply: the number of new members when the CH option is not used.
- Integer reply: the number of new or updated members when the CH option is used.
- Bulk string reply: the updated score of the member when the INCR option is used.
History
- Starting with Redis version 2.4.0: Accepts multiple elements.
- Starting with Redis version 3.0.2: Added the
XX,NX,CHandINCRoptions. - Starting with Redis version 6.2.0: Added the
GTandLToptions.