詳解Redis SORT命令

本專欄與Redis相關的文章html

Redis Sentinel機制與用法(一)
Redis Sentinel機制與用法(二)
Jedis的JedisSentinelPool源代碼分析
Jedis的Sharded源代碼分析
Redis 主從 Replication 的配置
詳解Redis SORT命令
JedisCommand接口說明redis

基本使用

命令格式: SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] segmentfault

默認狀況下,排序是基於數字的,各個元素將會被轉化成雙精度浮點數來進行大小比較,這是SORT命令最簡單的形式,也就是下面這種形式:微信

SORT mylistmarkdown

若是mylist是一個包含了數字元素的列表,那麼上面的命令將會返回升序排列的一個列表。若是想要降序排序,要使用DESC描述符,以下所示:編輯器

SORT mylist DESC性能

若是mylist包含的元素是string類型的,想要按字典順序排列這個列表,那麼就要用到ALPHA描述符,以下所示:編碼

SORT mylist ALPHAspa

Redis是基於UTF-8編碼來處理數據的, 要確保你先設置好了!LC_COLLATE環境變量。code

對於返回的元素個數也是能夠進行限制的,只須要使用LIMIT描述符。使用這個描述符,你須要提供偏移量參數,來指定須要跳過多少個元素,返回多少個元素。 下面這個例子將會返回一個已經排序好了的列表中的10個元素,從下標爲0開始:

SORT mylist LIMIT 0 10

幾乎所有的描述符均可以同時使用。例以下面這個例子所示,它將會返回前5個元素,以字典順序降序排列:

SORT mylist LIMIT 0 5 ALPHA DESC

經過外部key來排序

有時候,你會想要用外部的key來做爲權重去排列列表或集合中的元素,而不是使用列表或集合中原本就有的元素來排列。
下面以一個例子來解釋:
假設如今有一張這樣的表(順便吐槽一下,爲何這個markdown編輯器不支持表格,非要寫html代碼嗎),有商品id,商品價格,以及商品的重量。
圖片描述

首先將上述表格的數據導入到redis中(redis版本:2.8.6)

127.0.0.1:6379> lpush gid 1
(integer) 1
127.0.0.1:6379> lpush gid 2
(integer) 2
127.0.0.1:6379> lpush gid 3
(integer) 3
127.0.0.1:6379> lpush gid 4
(integer) 4
127.0.0.1:6379> set price_1 20
OK
127.0.0.1:6379> set price_2 40
OK
127.0.0.1:6379> set price_3 30
OK
127.0.0.1:6379> set price_4 10
OK
127.0.0.1:6379> set weight_1 3
OK
127.0.0.1:6379> set weight_2 2
OK
127.0.0.1:6379> set weight_3 4
OK
127.0.0.1:6379> set weight_4 1
OK

默認狀況下對gid排序,只會按gid的值來排序

127.0.0.1:6379> sort gid
1) "1"
2) "2"
3) "3"
4) "4"

可是經過BY描述符,能夠指定gid按照別的key來排序。例如我想要按照商品的價格來排序:

127.0.0.1:6379> sort gid by price_*
1) "4"
2) "1"
3) "3"
4) "2"

能夠看到,gid爲4的商品價格最低,爲10,gid爲2的商品價格最高,爲40。

在這裏,price_*中的*是一個佔位符,先會把gid的值取出,代入到*中,再去查找price_*的值。例如在本例中,price_*中的*會分別被1,2,3,4代替,而後去取price_1,price_2,price_3,price_4的值來進行排序。

跳過排序(不進行排序)

BY描述符也可使用一個根本不存在的key來做爲排序規則,則直接致使的結果就是不進行任何排序。 這看上去彷佛沒什麼用,可是若是你想要取得外部的keys時,跳過排序就很是有用了,這也會減小性能損耗。

要理解不排序的好處,首先要先了解一下GET描述符。
使用GET描述符,能夠根據排序結果取出外部鍵值。例如如下命令:

127.0.0.1:6379> sort gid get price_*
1) "20"
2) "40"
3) "30"
4) "10"

先對gid排序,而後再分別取出price_{gid}的值。

也可使用多個GET,獲取多個外部key的值,例如:

127.0.0.1:6379> sort gid get price_* get weight_*
1) "20" # 這是price
2) "3"  # 這是weight,如下類推
3) "40"
4) "2"
5) "30"
6) "4"
7) "10"
8) "1"

get也可使用#來獲取被排序的key的值,例如:

127.0.0.1:6379> sort gid get # get price_*
1) "1"  #這裏取出的就是gid
2) "20" #這裏是price,如下類推
3) "2"
4) "40"
5) "3"
6) "30"
7) "4"
8) "10"

經過結合不排序和GET,可以在不排序的狀況下,一次取得多個key的值。例如:

127.0.0.1:6379> sort gid by no-existed get # get price_* get weight_*
 1) "4"   #這是gid
 2) "10"  #這是price
 3) "1"   #這是weight,如下類推
 4) "3"
 5) "30"
 6) "4"
 7) "2"
 8) "40"
 9) "2"
10) "1"
11) "20"
12) "3"

將排序結果保存在Redis中

默認狀況下,排序結果會返回給客戶端。使用STORE描述符,能夠將結果存儲在指定key上,若是Key已經存在,則覆蓋。而不將排序結果返回給客戶端。用法以下:

SORT mylist BY weight_* STORE resultkey

下面舉一個例子:

127.0.0.1:6379> rpush num 1 3 5
(integer) 3
127.0.0.1:6379> rpush num 2 4 6
(integer) 6
127.0.0.1:6379> lrange num 0 -1
1) "1"
2) "3"
3) "5"
4) "2"
5) "4"
6) "6"
127.0.0.1:6379> sort num store num_sorted
(integer) 6
127.0.0.1:6379> lrange num_sorted 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"

將哈希表做爲GET或BY的參數

能夠將哈希表的字段做爲GET或者BY的參數,用法以下:

SORT mylist BY weight_*->fieldname GET object_*->fieldname

對於前面所用到的例子:
圖片描述

咱們能夠不把price_{gid}和weight_{id}用string類型來保存,而是對於每個gid,建立一個包含price和weight字段的hash表good_info_{gid}來存儲商品信息。

127.0.0.1:6379> hmset good_info_1 price 20 weight 3
OK
127.0.0.1:6379> hmset good_info_2 price 40 weight 2
OK
127.0.0.1:6379> hmset good_info_3 price 30 weight 4
OK
127.0.0.1:6379> hmset good_info_4 price 10 weight 1
OK

以後, by 和 get 選項均可以用 key->field 的格式來獲取哈希表中的域的值, 其中 key 表示哈希表鍵, 而 field 則表示哈希表的域:

127.0.0.1:6379> sort gid by good_info_*->price
1) "4"
2) "1"
3) "3"
4) "2"
127.0.0.1:6379> sort gid by good_info_*->price get good_info_*->weight
1) "1"
2) "3"
3) "4"
4) "2"

返回值

若是沒有使用 store 描述符,返回列表形式的排序結果。
若是使用 store 參數,返回排序結果的元素數量。

參考資料

Redis官網SORT命令介紹

掃一掃關注個人微信公衆號

相關文章
相關標籤/搜索