Программы
Сортированные множества в Redis

Сортированные множества в Redis

Сортированные множества или sorted sets — одна из структур данных Redis. Интересна она хотя бы тем, что не так часто встречается как таковая (даже вне рассмотрения Redis). А посему — давайте глубже копнём — что с ними будем делать.

Как и в случае со списками и множествами, в сортированных множествах можно хранить не скаляры, а именно множества (можно было догадаться). Как и у множеств, у sorted sets поддерживается уникальность элементов. Однако, в дополнение к этому добавляется значение score к каждому элементу, что позволяет упорядочивать элементы во множестве.

127.0.0.1:6379> zadd langs 1 python
(integer) 1
127.0.0.1:6379> zadd langs 2 perl
(integer) 1
127.0.0.1:6379> zadd langs 3 php
(integer) 1
127.0.0.1:6379> zadd langs 3 perl
(integer) 0
127.0.0.1:6379> zrange langs 0 100
1) "python"
2) "perl"
3) "php"

Синтаксис команды zadd — ключ, значение (значения). Только значение в sorted set — пара (score, element).

zrange — получить список элементов (с … по …) из множества. Элементы упорядочены по score. Можно указывать отрицательные границы — будет считать с конца.

127.0.0.1:6379> zadd langs 2 ruby
(integer) 1
127.0.0.1:6379> zrevrange langs -2 -1
1) "ruby"
2) "python"

zrevrange — то же самое, что и range, только считаем, что элементы упорядочены по score от большего к меньшему.

127.0.0.1:6379> zcard langs
(integer) 4

zcard — количество элементов во множестве.

Аналогично можно получить количество через zcount:

127.0.0.1:6379> zcount langs -inf +inf
(integer) 4
127.0.0.1:6379> zcount langs 2 3
(integer) 3

С другой стороны, вы ещё можете использовать её для получения количества элементов, score которого с … по …

127.0.0.1:6379> zincrby langs 2 ruby
"4"

— как «двигать» элементы во множестве.

127.0.0.1:6379> zadd football 1 "Спартак" 2 "Зенит" 3 "Локомотив"
(integer) 3
127.0.0.1:6379> zadd hockey 1 "Локомотив" 2 "Спартак"
(integer) 2
127.0.0.1:6379> zinterstore result 2 football hockey
(integer) 2
127.0.0.1:6379> zrange result 0 -1 withscores
1) "\xd0\xa1\xd0\xbf\xd0\xb0\xd1\x80\xd1\x82\xd0\xb0\xd0\xba"
2) "3"
3) "\xd0\x9b\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbc\xd0\xbe\xd1\x82\xd0\xb8\xd0\xb2"
4) "4"

Небольшой рейтинг команд по футболу и хоккею. В итоге — получаем «общий зачёт» с помощью zinterstore, который мы ограничиваем 2-мя командами. Score — сумма score по множествам.

zlexcount key min max — получение числа элементов, находящихся включительно с min до max, но в порядке не score, а лексикографическом.

zrangebylex — то же самое, но применительно к zrange.

127.0.0.1:6379> zrangebyscore langs 1 3 withscores
1) "python"
2) "1"
3) "perl"
4) "3"
5) "php"
6) "3"
127.0.0.1:6379> zrangebyscore langs 1 (3 withscores
1) "python"
2) "1"

А вот мы получаем range именно по score — то есть «с такого score по такой». Здесь же пример с использованием скобочки — в значении «не включая».

127.0.0.1:6379> zrank langs ruby
(integer) 3

Получить номер элемента в ранжированной по score последовательности (номер начинается с 0).

127.0.0.1:6379> zrem football "Спартак"
(integer) 1

«Дисквалифицировали» команду «Спартак» из футбольных соревнований. zscore key element — получить score для элемента во множестве.

127.0.0.1:6379> zunionstore result 2 football hockey WEIGHTS 1 2
(integer) 3
127.0.0.1:6379> zrange result 0 -1 withscores
1) "\xd0\x97\xd0\xb5\xd0\xbd\xd0\xb8\xd1\x82"
2) "2"
3) "\xd0\xa1\xd0\xbf\xd0\xb0\xd1\x80\xd1\x82\xd0\xb0\xd0\xba"
4) "4"
5) "\xd0\x9b\xd0\xbe\xd0\xba\xd0\xbe\xd0\xbc\xd0\xbe\xd1\x82\xd0\xb8\xd0\xb2"
6) "5"

Получили результирующую общую зачётную таблицу. Weights — говорит о том, что при суммирование score из разных множеств (футбола и хоккея), мы очки хоккея удваиваем.