Раздел 37 · Redis с нуля

Хеши: объекты и поля

junior~20 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

В прошлом уроке множество хранило набор меток, но у метки нет своих полей. А карточка книги состоит из полей: название, автор, цена, остаток на складе. Пока мы раскладывали их по отдельным ключам book:1:title, book:1:price, и карточка расползалась на десяток ключей. Хеш собирает её в один.

Анкета на одном листе

Представь анкету в отделе кадров. На одном листе написано: «Имя: Ольга. Город: Казань. Стаж: 5». Чтобы узнать город, не нужна вторая папка, ты смотришь в нужную строку того же листа. Исправить стаж можно, не переписывая всю анкету.

Хеш в Redis устроен так же: один ключ, внутри пары «поле и значение». Похоже на объект в JavaScript или на строку таблицы в PostgreSQL, только вложенных объектов нет: значение поля всегда строка.

Карточка книги

Записываем карточку «Мастера и Маргариты» командой HSET. После ключа идут пары: поле, значение, поле, значение:

127.0.0.1:6379> HSET book:1 title "Master and Margarita" author Bulgakov price 690 year 1967
(integer) 4
127.0.0.1:6379> HGET book:1 title
"Master and Margarita"
127.0.0.1:6379> HGET book:1 isbn
(nil)

HSET отвечает, сколько полей появилось впервые. HGET читает одно поле, а несуществующее поле даёт (nil), как несуществующий ключ.

Несколько полей за раз читает HMGET, а всю карточку HGETALL:

127.0.0.1:6379> HMGET book:1 title price isbn
1) "Master and Margarita"
2) "690"
3) (nil)
127.0.0.1:6379> HGETALL book:1
1) "title"
2) "Master and Margarita"
3) "author"
4) "Bulgakov"
5) "price"
6) "690"
7) "year"
8) "1967"

HGETALL отдаёт плоский список, где поля и значения чередуются. Клиентские библиотеки сами собирают из него объект. Порядок полей Redis не обещает: у маленьких хешей он совпадает с порядком добавления, у больших будет произвольным.

Поменять одно поле

Цена упала, а на склад привезли книги. Тот же HSET обновит цену и добавит новое поле:

127.0.0.1:6379> HSET book:1 price 650 stock 12
(integer) 1
127.0.0.1:6379> HGETALL book:1
 1) "title"
 2) "Master and Margarita"
 3) "author"
 4) "Bulgakov"
 5) "price"
 6) "650"
 7) "year"
 8) "1967"
 9) "stock"
10) "12"

Ответ 1: новое поле одно, stock. Цена тоже поменялась, но поле price уже было, поэтому в счёт не попало. Остальные поля остались на месте.

Ещё несколько команд для работы с полями:

127.0.0.1:6379> HLEN book:1
(integer) 5
127.0.0.1:6379> HKEYS book:1
1) "title"
2) "author"
3) "price"
4) "year"
5) "stock"
127.0.0.1:6379> HEXISTS book:1 isbn
(integer) 0
127.0.0.1:6379> HDEL book:1 year isbn
(integer) 1

HLEN считает поля, HKEYS перечисляет их имена, а HVALS значения. HEXISTS проверяет, есть ли поле. HDEL удаляет поля и отвечает, сколько удалил: year был, isbn не было.

Если поле нужно записать только когда его ещё нет, есть HSETNX. Это тот же приём, что SET ... NX из урока про строки:

127.0.0.1:6379> HSETNX book:1 title "Heart of a Dog"
(integer) 0
127.0.0.1:6379> HSETNX book:1 isbn 978-5-17-090
(integer) 1

Название уже было, и его не перезаписало. ISBN не было, и он появился.

урок из курса

Урок из курса «Redis с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.