【Redis】常見的資料型態與相關操作指令


https://www.pexels.com/zh-tw/photo/46274/

Redis 是一款以「key-value」形式來儲存內容的資料庫。它就像字典,是透過一個「key」去查閱對應的值,這點與其他常見的資料庫是大大的不同。此外,這款資料庫支援儲存數種有趣的資料型態。

本文將介紹 Redis 主要的 5 種資料型態,並從它們的操作指令中整理出一部份來示範。

一、先備知識

如果讀者單純想認識指令,但沒有安裝好 Redis 也沒關係。官方提供了線上的 command line 工具可使用。
https://try.redis.io/

在開始練習前,首先最好要知道 3 個指令。

第一個是 KEYS,它能列出資料庫中目前已有的 key。

KEYS *
(empty array)

第二個是 DEL,它能一次刪除一至多筆資料。以下範例是刪除 key 為「fullName」與「age」的資料。

DEL fullName age
(integer) 2

第三個是 SELECT,是用來切換資料庫,讀者可想成是切換到另一個資料表。它們之間以一個號碼(index)來區別,且資料是分開的。

SELECT 0
OK

SELECT 1
OK

我們能注意到,每次執行完指令後,Redis 都會回傳結果。


二、字串型態(String)

(一)讀寫

字串是最基礎的型態。儲存字串時會使用 SET 指令,而取出則用 GET

以下範例是儲存 key 為「fullName」,value 為「Harry Potter」的資料,隨後再取出。

SET fullName "Harry Potter"

GET fullName
"Harry Potter"

使用指令時,特地將參數用引號包起來的原因是為了不要被當成不同的參數,造成語法錯誤,否則是可以省略的。

(二)數值的增減

事實上,Redis 並沒有數值型態,所以也必須用字串來儲存這類資料。然而若可辨識出是數值,我們還是能進行一些數字增減的操作。

將整數做遞增,會使用 INCR 指令,意義為 increase;而遞減則是 DECR

SET age 18

INCR age
(integer) 19

若要增加指定的整數,指令為 INCRBY,減少則是 DECRBY。而 INCRBYFLOAT 則是用浮點數來增減。

SET total 60

INCRBY total 8
(integer) 68

INCRBYFLOAT total -3.2
(integer) 64.8

更多 String 指令請參考以下網頁:
https://redis.io/commands/?group=string
https://www.runoob.com/redis/redis-strings.html


三、雜湊型態(Hash)

Hash 就像 Java 語言的「HashMap」,可存放多組 key-value,適合用來描述一個物件。其中 value 固定是 String 型態。

(一)寫入與取得鍵值

使用 HSET 指令,可放入一至多組鍵值。

以下範例是在 key 為「product」的 Hash 中放入 3 組鍵值。

HSET product vendor Vincent price 2.5 comments 6

讀者能注意到,參數是以「key 1、value 1、key 2、value 2 …」的順序寫下去。

使用 HGET 指令,可取得一個指定的 key 的值。

HGET product comments
"6"

另外,若鍵值的 value 可辨識為數值,則能使用 HINCRBYHINCRBYFLOAT 來增減值。以下範例是將 comments 的值增加 1,price 的值減少 0.3。

HINCRBY product comments 1
(integer) 7

HINCRBYFLOAT product price -0.3
"2.2"

(二)列出鍵值

使用 HKEYSHVALS 指令,分別可列出所有的 key 與 value。

HKEYS product
1) "vendor"
2) "proce"
3) "comments"

HVALS product
1) "Vincent"
2) "2.2"
3) "7"

使用 HGETALL 指令,可列出所有的 key-value。

HGETALL product
1) "vendor"
2) "Vincent"
3) "price"
4) "3.2"
5) "comments"
6) "7"

(三)刪除值

使用 HDEL 指令,可刪除一至多個 key-value。

HDEL product price

更多 Hash 指令請參考以下網頁:
https://redis.io/commands/?group=hash
https://www.runoob.com/redis/redis-hashes.html

四、列表型態(List)

List 可以存放多個 String,在操作上與資料結構領域中的「佇列」(queue)有幾分相似。

(一)放入與取得元素

使用 LPUSH 指令,可從 List 的左邊依序放入一至多個元素;從右邊則用 RPUSH

以下範例是在 key 為「students」的 List 放入元素。

LPUSH students David Cindy Bella Anna
(integer) 4

RPUSH students Ella Frank Gina Harry
(integer) 8

使用 LINDEX 指令,可取出指定位置(index,從 0 開始)的元素。若不存在,則回傳「nil」(空值)。位置參數也能傳入負值,代表從 List 的右邊數過來。

以下範例是先後取得第 2 個和最後一個元素。

LINDEX students 1
"Bella"

LINDEX students -1
"Harry"

(二)列出元素

使用 LRANGE 指令,可查看指定位置範圍的元素。

指令除了 key,還接收兩個位置參數,分別代表起點與終點。其中終點參數允許超出 List 的邊界,並不會報錯。

接續前面 students 的 List,以下範例是列出第 1 個到第 3 個元素。

LRANGE students 0 2
1) "Anna"
2) "Bella"
3) "Cindy"

此外,這兩個位置參數同樣能使用負數。以下範例是列出第 6 個到最後一個元素。

LRANGE students 5 -1
1) "Frank"
2) "Gina"
3) "Harry"

要注意的是,無論是否使用負數,起點都必須在終點左邊,否則結果會是空的。以下是一個錯誤示範。

LRANGE students 6 -6
(empty array)

由於在 8 個元素的 List 中,起點參數指向第 7 個,終點參數指向第 3 個,因此沒有結果。

(三)設定元素

使用 LSET 指令,可將指定位置的元素取代成新的值。

LSET students 2 Cindy

(四)刪除元素

使用 LREM 指令,可刪除指定的值。甚至能定義要從哪個方向刪除幾個。

以下範例是從左邊刪除 2 個「Grape」值。

RPUSH fruits Apple Grape Banana Grape Grape

LREM fruits 2 Grape
(integer) 2

關於指令中的數量參數,正數代表從左邊,而負數是右邊。若給予 0,則代表刪除所有指定的值。

(五)彈出元素

使用 LPOP 指令,可移除 List 最左邊的一至多個元素,並回傳它們。從右邊則用 RPOP

以下範例是從左邊彈出 1 個元素,再從右邊彈出 2 個。

RPUSH beverage "black tea" "green tea" "coffee" "milk"

LPOP beverage
"black tea"

RPOP beverage 2
1) "milk"
2) "coffee"

更多 List 指令請參考以下網頁:
https://redis.io/commands/?group=list
https://www.runoob.com/redis/redis-lists.html


五、集合型態(Set)

Set 能儲存多個 String,且資料不重複,彼此間也沒有先後順序。

(一)添加元素

使用 SADD 指令,可添加一至多個元素。

以下範例是在 key 為「students」的集合中添加 6 個元素。

SADD students Anna Bella Cindy David Ella Frank

(二)列出元素

使用 SMEMBERS 指令,可列出所有元素。

SMEMBERS students
1) "Cindy"
2) "David"
3) "Anna"
4) "Bella"
5) "Frank"
6) "Ella"

(三)移除元素

使用 SREM 指令,可移除一至多個元素。

SREM students Ella Frank

(四)集合運算

我們可聯合多個集合,進行一些運算。以下是範例會用到的 2 個集合。

SADD students Anna Bella Cindy David
SADD employees Bella David Ella

使用 SINTER 指令,可得到交集。

SINTER students employees
1) "Bella"
2) "David"

使用 SUNION 指令,可得到聯集。

SUNION students employees
1) "David"
2) "Bella"
3) "Anna"
4) "Cindy"
5) "Ella"

使用 SDIFF 指令,可得到參數中第一個集合獨有的元素,也就是差集。

SDIFF students employees
1) "Anna"
2) "Cindy"

SDIFF employees students
1) "Ella"

更多 Set 指令請參考以下網頁:
https://redis.io/commands/?group=set
https://www.runoob.com/redis/redis-sets.html

五、有序集合型態(Sorted Set)

Sorted Set 可存放一對一對的 String 與自定義的「分數」,且不會有重複的 String。還能用於簡單的數值計算。

(一)添加元素

使用 ZADD 指令,可添加一至多個元素,或更新已存在 String 的分數。

ZADD receipt 70 Coffee 50 Sandwich 55 Hamburger

在添加元素的參數中,是先寫分數,再寫 String。以上範例添加了 3 筆。

(二)列出元素

Sorted Set 是根據分數來遞增排序。使用 ZRANGE 指令,可列出指定位置範圍的元素,也就是根據分數名次。位置參數也可使用負數,代表從分數最高的元素數過來。

ZRANGE receipt 0 -1
1) "Sandwich"
2) "Hamburger"
3) "Coffee"

加上「BYSCORE」的選項,則會變為列出分數在指定範圍內的元素。

ZRANGE receipt 50 60 BYSCORE
1) "Sandwich"
2) "Hamburger"

加上「WITHSCORES」的選項,就能一併列出分數。

ZRANGE receipt 50 60 BYSCORE WITHSCORES
1) "Sandwich"
2) "50.0"
3) "Hamburger"
4) "55.0"

(三)取得分數

使用 ZSCORE 指令,可取得一個指定元素的分數。

ZSCORE receipt Sandwich
"50"

(四)移除元素

使用 ZREM 指令,可移除一至多個元素。

ZREM receipt Coffee Tea

使用 ZREMRANGEBYSCORE 指令,可移除指定分數範圍內的元素。

ZREMRANGEBYSCORE receipt 70 80

使用 ZREMRANGEBYRANK 指令,可移除指定位置(名次)範圍內的元素。

ZREMRANGEBYRANK receipt 2 -1

(五)聚合運算

我們可以聯合多個 Sorted Set 進行分數的運算,以下是範例會用到的 3 個集合。

ZADD english 80 Anna 74 Bella 85 Cindy
ZADD math 88 Anna 92 Bella
ZADD chinese 70 Bella 90 Cindy

使用 ZINTER 指令,可列出這些集合的交集元素。

ZINTER 2 english math
1) "Bella"
2) "Anna"

參數中的「2」代表集合的數量。

加上「WITHSCORES」選項,還能一併列出分數。而對於相同 String 的元素,我們可透過「AGGREGATE」選項,決定其分數要相加(SUM)、取最大值(MAX)或最小值(MIN)。

ZINTER 2 english math AGGREGATE SUM WITHSCORES
1) "Bella"
2) "166"
3) "Anna"
4) "168"

加上「WEIGHTS」選項,可在計算分數時給予權重

ZINTER 2 english math WEIGHTS 3 4 AGGREGATE SUM WITHSCORES
1) "Bella"
2) "590"
3) "Anna"
4) "592"

使用 ZUNION 指令,則是將所有集合的元素一同用來計算分數,用法與 ZINTER 相同。

以下範例是列出 Anna、Bella 與 Cindy 在 3 個集合中的最高分。

ZUNION 3 english math chinese AGGREGATE MAX WITHSCORES
1) "Cindy"
2) "90"
3) "Anna"
4) "88"
5) "Bella"
6) "92"

更多 Sorted Set 指令請參考以下網址:
https://redis.io/commands/?group=sorted-set
https://www.runoob.com/redis/redis-sorted-sets.html

上一篇:【Redis】基本介紹與在 Windows Docker 上安裝

下一篇:【Redis】在 Spring Boot 使用 Redis Template 實現快取

留言