Redis ZADD Command Explained

In Redis, the ZADD command is used to add one or more members to a sorted set, or to update the score for members that already exist in the sorted set.

It returns the number of elements added to the sorted set, or the number of elements updated if the CH argument is used.

Syntax

The syntax for the ZADD command goes like this:

ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member
  ...]

Where:

  • key is the name of the sorted set
  • score is the score to be associated with the member
  • member is the value to be added to the sorted set
  • [score member …] means that we have the option to add/update multiple elements at once.

Here’s what the other options are for:

  • NX: Only adds new elements. Doesn’t update existing elements.
  • XX: Only updates elements that already exist. Doesn’t add new elements.
  • GT: Only updates existing elements if the new score is greater than the current score. This flag doesn’t prevent us from adding new elements.
  • LT: Only updates existing elements if the new score is less than the current score. This flag doesn’t prevent us from adding new elements.
  • CH: Modifies the return value to the total number of elements changed. By default, the return value of ZADD only counts the number of new elements added (not changed). However, this flag modifies this so that we get the number of elements that were changed. Changed elements are new elements added and elements already existing for which the score was updated. Existing elements being updated with the same score are not counted.
  • INCR: When this option is specified ZADD acts like the ZINCRBY command. Only one score-element pair can be specified in this mode.

The GTLT and NX options are mutually exclusive.

Example

Here’s a basic example to demonstrate how it works:

ZADD scores 215 player:1 157 player:2 327 player:3

Result:

(integer) 3

In my case the sorted set didn’t exist, and so it was created and the three elements were added as specified.

Let’s use ZRANGE to return the contents of the sorted set:

ZRANGE scores 0 -1

Result:

1) "player:2"
2) "player:1"
3) "player:3"

The elements are sorted in ascending order based on their scores.

We can change this to descending order by using the REV argument:

ZRANGE scores 0 -1 REV

Result:

1) "player:3"
2) "player:1"
3) "player:2"

We can also use ZADD to update existing elements:

ZADD scores 235 player:1 187 player:2

Result:

(integer) 0

The CH Argument

By default, the return value only counts the number of new elements added (not changed). That’s why 0 is returned in the above example.

We can use the CH argument to return the number of elements that were changed. This includes existing elements that were changed, and also any new ones that were added:

ZADD scores CH 240 player:1 192 player:2 521 player:4

Result:

(integer) 3

In this case, the two existing elements were changed and one new one was added. We used the CH argument, and so we get an integer reply of 3.

Here’s what happens when we run the exact same code again:

ZADD scores CH 240 player:1 192 player:2 521 player:4

Result:

(integer) 0

We get 0 because nothing was updated or added. Existing elements being updated with the same score are not counted.

The INCR Argument

We can use the INCR argument to increment an element’s value. The INCR argument works just like the ZINCRBY command. However, when using this option, only one score-element pair can be updated at a time.

ZADD scores INCR 10 player:1

Result:

"250"

When we use this option, the return value is the value of the element’s score after the INCR operation has taken place. In this example, the score was increased by 10 from 240 to 250.

We can use a negative number to decrement the score:

ZADD scores INCR -5 player:1

Result:

"245"

In this case I decremented the score by 5, so that the resulting score is 245.

The XX Argument

We can use the XX argument to update only those elements that already exist:

ZADD scores XX 267 player:1 700 player:5

Result:

(integer) 0

Our sorted set already had player:1 but not player:5. Therefore, because we used the XX argument, player:1 was updated but player:5 wasn’t added. We got 0 because no new elements were added.

Let’s check our sorted set to confirm this:

ZRANGE scores 0 -1

Result:

1) "player:2"
2) "player:1"
3) "player:3"
4) "player:4"

As expected, player:5 was not added.

The NX Argument

Conversely, we can use the NX argument so that it only adds those elements that don’t already exist. Any existing elements aren’t updated.

ZADD scores NX 800 player:1 700 player:5

Result:

(integer) 1

Let’s check the sorted set:

ZRANGE scores 0 -1

Result:

1) "player:2"
2) "player:1"
3) "player:3"
4) "player:4"
5) "player:5"

We can see that player:5 has now been added to our sorted set. It’s also apparent that player:1‘s score wasn’t updated, otherwise it occupy a position further up the sorted set.

We can confirm this with the ZMSCORE command:

ZMSCORE scores player:1

Result:

1) "267"

The GT Argument

The GT argument specifies that existing elements will only be updated if the new score is greater than the current score. It doesn’t prevent us from adding new elements though.

ZADD scores GT 200 player:1

Result:

(integer) 0

Let’s check:

ZMSCORE scores player:1

Result:

1) "267"

It hasn’t changed because the new value is less than the existing score.

Let’s increase the new score:

ZADD scores GT 300 player:1

Result:

(integer) 0

We still get 0 because nothing was added (and I didn’t use the CH argument). But now let’s check the score:

ZMSCORE scores player:1

Result:

1) "300"

It has increased as expected.

The LT Argument

The LT argument specifies that existing elements will only be updated if the new score is less than the current score. Like the GT argument, it doesn’t prevent us from adding new elements.

Let’s run an example. This time we’ll use the CH argument to tell us whether or not the element has been updated:

ZADD scores LT CH 330 player:1

Result:

(integer) 0

Nothing was changed because the new value is greater than the existing value.

Let’s decrease the value. While we’re at it, let’s also add a new element:

ZADD scores LT CH 230 player:1 128 player:6

Result:

(integer) 2

This time we can see that two changes took place. One was an update and the other was an addition.

Let’s check:

ZMSCORE scores player:1 player:6

Result:

1) "230"
2) "128"

As expected.

Sorting Lexicographically

If multiple elements share the same score, they’re sorted lexicographically. To demonstrate this, let’s set all our elements to zero:

ZADD scores CH 0 player:1 0 player:2 0 player:3 0 player:4 0 player:5 0 player:6

Result:

(integer) 6

Now let’s use ZRANGE to return all elements:

ZRANGE scores 0 -1

Result:

1) "player:1"
2) "player:2"
3) "player:3"
4) "player:4"
5) "player:5"
6) "player:6"

As expected. And while we’re at it, let’s sort them in reverse:

ZRANGE scores 0 -1 REV

Result:

1) "player:6"
2) "player:5"
3) "player:4"
4) "player:3"
5) "player:2"
6) "player:1"

More Information

See the Redis documentation for more information and for any changes that might have been implemented to the command after this article was published.