Python–Redis實戰:第三章:Redis命令:第五節:有序集合

Mark發表於2019-02-16

上一篇文章:Python–Redis實戰:第三章:Redis命令:第四節:雜湊
下一篇文章:Python–Redis實戰:第三章:Redis命令:第六節:釋出與訂閱

和雜湊儲存著鍵與值之間的對映類似,有序集合也儲存著成員與分值之間的對映,並且提供了分值處理命令,已經根據分值大小有序的獲取(fetch)和掃描(scan)成員和分值的命令。本書曾在第一章使用有序集合實現過基於釋出時間排序的文章列表和基於投票數量排序的文章列表,還在第二章使用有序集合儲存過cookie的過期時間。

這些分值在Redis中以IEEE754雙精度點數的格式儲存。

本節將對操作有序集合的命令進行介紹,其中包括向有序集合新增新元素的命令、更細已有元素的命令、以及對有序集合進行交集運算和並集運算的命令。

下表展示了一部分常用的有序集合命令:

命令 用例 用例描述
zadd zadd key-name score memeber [score member …] 將帶有給定分值的成員新增到有序集合裡面
zrem zrem key-name member [member …] 從有序集合裡面移除給定的成員,並返回被移除成員的數量
zcard zcard key-name 返回有序集合包含的成員數量
zincrby zincrby key-name increment member 將merber成員的分值加上increment
zcount zcount key-name min max 返回分值介於min和max之間的成員數量
zrank zrank key-name member 返回成員member有序集合中的排名。
zscore zsore key-name member 返回成員member的分值
zrange zrange key-name start stop [WITHSCORES] 返回有序集合中排名介於start和stop之間的成員,如果給定了可選的WITHSCORES選項,那麼命令會將成員的分值也一併返回。

例項:

import redis # 匯入redis包包


# 與本地redis進行連結,地址為:localhost,埠號為6379
r = redis.StrictRedis(host=`localhost`, port=6379)

r.delete(`zset-key`)

print(r.zadd(`zset-key`,3,`a`,2,`b`,1,`c`))

print(r.zcard(`zset-key`))

print(r.zincrby(`zset-key`,`c`,3))

print(r.zscore(`zset-key`,`b`))

print(r.zrank(`zset-key`,`c`))

#返回介於0-3之間的成員數量
print(r.zcount(`zset-key`,0,3))

print(r.zrem(`zset-key`,`b`))

print(r.zrange(`zset-key`,0,-1,withscores=True))

結果:

3
3
4.0
2.0
2
2
1
[(b`a`, 3.0), (b`c`, 4.0)]

因為zadd、zrem、zincrby、zscore和zrange都已經在第一章和第二章介紹過了,所以讀者應該不會對它們感到陌生。zcount命令和其他命令不太相同,它主要擁擠計算分值在給定範圍內的成員數量。

下表展示了另外一些非常有用的有序集合命令:

有序集合的範圍型資料獲取命令和範圍型資料刪除命令,以及並集命令和交集命令:

命令 用例 用例描述
zrevrank zrevrank key-name merber 返回有序集合裡面成員member的排名,成員按照分值從大到小排列
zrevrange zrevrange key-name start stop [WITHSCORES] 返回有序集合給定排名範圍內的成員,成員按照分值從大到小排列
zrangebysocre zrangebyscore by min max [WITHSCORES] [LIMIT offset count] 返回有序集合中,分值介於min和max之間的所有成員。
zrevrangebyscore zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count] 獲取有序集合中分值介於min和max之間的所有成員,並按照分值從大到小的順序來返回它們。
zremrangebyrank zremrangebyrank key-name start stop 移除有序集合中排名介於start和stop之間的所有成員。
zremrangebyscore zremrangebyscore key-name min max 移除有序集合中分值介於min和max之間的所有成員。
zinterstore zinterstore dest-key key-count key [key …] 對給定的有序集合執行類似於集合的交集運算。
zunionstore zunionstore dest-key key-count key [key …] [weights weight [weight …]][aggregate summinmax] 對給定的有序集合執行類似於集合的並集運算。

上表展示的命令裡面,有幾個是之前沒介紹過的新命令。除了使用逆序來處理有序集合之外,zrev*命令的工作方式和相對應的非逆序命令的工作方式完全一樣(逆序就是指元素按照從大到小地排列)。

例項:

import redis # 匯入redis包包


# 與本地redis進行連結,地址為:localhost,埠號為6379
r = redis.StrictRedis(host=`localhost`, port=6379)

r.delete(`zset-key1`)
r.delete(`zset-key2`)
r.delete(`zset-key-i`)
r.delete(`zset-key-u`)
r.delete(`zset-key-u2`)
r.delete(`set-1`)

#首先建立兩個有序集合
#a b c d
#1 2 3
# 4 1 0
print(r.zadd(`zset-key1`,1,`a`,2,`b`,3,`c`))
print(r.zadd(`zset-key2`,4,`b`,1,`c`,0,`d`))


#zinterstore和zunionstore預設使用的聚合函式為sum,這個函式會把各個有序集合的成員的分值都加起來
print(r.zinterstore(`zset-key-i`,[`zset-key1`,`zset-key2`]))

print(r.zrange(`zset-key-i`,0,-1,withscores=True))

#使用者可以在執行並集運算和交集運算的時候傳入不同的聚合函式,共有sum、min、max三個聚合函式可選。
print(r.zunionstore(`zset-key-u`,[`zset-key1`,`zset-key2`],aggregate=`min`))

print(r.zrange(`zset-key-u`,0,-1,withscores=True))

print(r.sadd(`set-1`,`a`,`d`))

#使用者可以把集合作為輸入傳給zinterstore和zunionstore,命令會將集合看作是成員分值全為1的有序集合來處理。
print(r.zunionstore(`zset-key-u2`,[`zset-key1`,`zset-key2`,`set-1`]))

print(r.zrange(`zset-key-u2`,0,-1,withscores=True))

結果:

3
3
2
[(b`c`, 4.0), (b`b`, 6.0)]
4
[(b`d`, 0.0), (b`a`, 1.0), (b`c`, 1.0), (b`b`, 2.0)]
2
4
[(b`d`, 1.0), (b`a`, 2.0), (b`c`, 4.0), (b`b`, 6.0)]

有序集合的並集運算和交集運算在剛開始接觸時可能會比較難懂,我們將以表格來展示交集運算和並集運算的執行過程。

對兩個輸入有序集合執行【交集】運算並得到輸出有序集合

這次交集運算使用的是預設的聚合函式sum,所有輸出有序集合成員的分值都是通過加法計算得到的。

  • zset-key1:
a b c d
1 2 3
  • zset-key2
a b c d
4 1 0
  • zset-key-i
a b c d
6 4

執行r.zinterstore(`zset-key-i`,[`zset-key1`,`zset-key2`]),將使得同時存在於zset-key1和zset-key2裡面的元素被新增到z-set-key-i中。

對兩個輸入有序集合執行【並集】運算並得到輸出有序集合

並集運算和交集運算不同,只要某個成員存在於至少一個輸入有序集合裡面,那麼這個成員就會被包含在輸出有序集合裡面。下表展示了使用聚合函式min執行並集運算的過程,min函式在多個輸入有序集合都包含同一個成員的情況下,會將最小的那個分值設定Wie這個成員的輸出有序集合的分值。

  • zset-key1
a b c d
1 2 3
  • zset-key2
a b c d
4 1 0
  • zset-key-u
a b c d
1 2(取小的那個) 1(取小的那個) 0

執行r.zunionstore(`zset-key-u`,[`zset-key1`,`zset-key2`],aggregate=`min`),會將存在於zset-key1或者zset-key2裡面的元素通過min函式組合到zset-key-u裡面。

使用zunionstore命令來將兩個有序集合和一個集合組合成一個有序集合

  • zset-key1
a b c d
1 2 3
  • zset-key2
a b c d
4 1 0
  • set-1
a d
  • zset-key-u2
a b c d
2 6 4 1

執行r.zunionstore(`zset-key-u2`,[`zset-key1`,`zset-key2`,`set-1`]),將使得所有存在於zset-key1、zset-key2或者set-1裡面的元素都被新增到zset-key-u2裡面

後面講使用zinterstore和zunionstore來構建幾個不同型別的搜尋系統,並說明如果通過可選的weights引數來以幾種不同的防暑組合有序集合的分值,從而使得集合和有序集合可以用於解決更多問題。

讀者在開發應用的過程中,也許曾經聽說過釋出與訂閱(publish、subscribe)模式,又稱pub/sub模式,Redis也實現了這種模式,接下來的一節將對其進行介紹。

上一篇文章:Python–Redis實戰:第三章:Redis命令:第四節:雜湊
下一篇文章:Python–Redis實戰:第三章:Redis命令:第六節:釋出與訂閱

相關文章