Jedis裡SortedSet相關操作
阿新 • • 發佈:2019-02-01
Jedis裡的SortedSet 可以理解為有序集合或者優先佇列,每個key都是有分值的,所以可以應用於排行榜或者某個使用者的成就值 成就排名之類的關於分值排行相關
當然index也都是從0開始的,-1結尾的,有雙向性,預設排名是從小到大
Jedis jedis=new Jedis(); jedis.flushAll();//清空 /* * SortedSet有序集合(優先佇列) * 每個key有分值的 * 應用:排行榜 */ String rankKey="rankKey"; jedis.zadd(rankKey, 15,"jim"); jedis.zadd(rankKey, 35,"ben"); jedis.zadd(rankKey, 85,"candy"); jedis.zadd(rankKey, 75,"david"); jedis.zadd(rankKey, 95,"mei"); print(30,jedis.zcard(rankKey));//有多少kv對 print(31,jedis.zcount(rankKey,61,100));//在61到100分值的有幾人 print(32,jedis.zscore(rankKey, "candy"));//查詢某個使用者的分值 jedis.zincrby(rankKey, 10, "ben");//對某個人提分 print(33,jedis.zscore(rankKey, "ben")); jedis.zincrby(rankKey, 5, "lucy");//不存在某個人 對他提分 則新加入其中 print(34,jedis.zcount(rankKey,0,100)); print(35,jedis.zrange(rankKey, 0, 2));//排名前3位的 (預設從小到大) index從0開始 ************ print(36,jedis.zrevrange(rankKey, 0, 2));//排名前3位的 (從大到小)************ //tuple可以理解為元組 裡面有equals compareto等方法 for(Tuple tuple:jedis.zrangeByScoreWithScores(rankKey, 0, 100)){ print(37,tuple.getElement()+":"+String.valueOf(tuple.getScore())); } print(38,jedis.zrank(rankKey, "ben"));//ben排名第幾 排名從0開始 比如:成就值排名*************** print(39,jedis.zrevrank(rankKey, "ben"));//
30, 5
31, 3
32, 85.0
33, 45.0
34, 6
35, [lucy, jim, ben]
36, [mei, candy, david]
37, lucy:5.0
37, jim:15.0
37, ben:45.0
37, david:75.0
37, candy:85.0
37, mei:95.0
38, 2
39, 3
具體方法:
/** * SortedSet(有序集合) * ZADD,ZCARD,ZCOUNT,ZINCRBY,ZRANGE,ZRANGEBYSCORE,ZRANK,ZREM,ZREMRANGEBYRANK,ZREMRANGEBYSCORE,ZREVRANGE * ZREVRANGEBYSCORE,ZREVRANK,ZSCORE,ZUNIONSTORE,ZINTERSTORE,ZSCAN,ZRANGEBYLEX,ZLEXCOUNT,ZREMRANGEBYLEX */ public class SortedSetTypeTest { private Jedis jedis; private static final String KEY = "sorted_set"; private static final String VALUE = "layman"; @Before public void setUp() { this.jedis = new Jedis(new JedisShardInfo("192.168.133.188", 6379)); } /** * ZADD key score member [[score member] [score member] ...] * 將一個或多個 member 元素及其 score 值加入到有序集 key 當中。 * 如果某個 member 已經是有序集的成員,那麼更新這個 member 的 score 值,並通過重新插入這個 member 元素,來保證該 member 在正確的位置上。 * score 值可以是整數值或雙精度浮點數。 * 如果 key 不存在,則建立一個空的有序集並執行 ZADD 操作。 * 當 key 存在但不是有序集型別時,返回一個錯誤。 */ @Test public void ZADD() { Map<String, Double> sourceMember = new HashMap<String, Double>(); for (int i = 0; i < 3; i++) { double score = getRandomInt(); sourceMember.put(VALUE + score, score); } jedis.zadd(KEY, sourceMember); ZRANGE(); } /** * ZCARD key * 返回有序集 key 的基數。 */ @Test public void ZCARD() { System.out.println(jedis.zcard(KEY)); } /** * ZCOUNT key min max * 返回有序集 key 中, score 值在 min 和 max 之間(預設包括 score 值等於 min 或 max )的成員的數量。 * 關於引數 min 和 max 的詳細使用方法,請參考 ZRANGEBYSCORE 命令。 */ @Test public void ZCOUNT() { System.out.println(jedis.zcount(KEY, "-inf", "+inf")); System.out.println(jedis.zcount(KEY, 24, 45)); } /** * ZINCRBY key increment member * 為有序集 key 的成員 member 的 score 值加上增量 increment 。 * 可以通過傳遞一個負數值 increment ,讓 score 減去相應的值,比如 ZINCRBY key -5 member ,就是讓 member 的 score 值減去 5 。 * 當 key 不存在,或 member 不是 key 的成員時, ZINCRBY key increment member 等同於 ZADD key increment member 。 * 當 key 不是有序集型別時,返回一個錯誤。 * score 值可以是整數值或雙精度浮點數。 */ @Test public void ZINCRBY() { ZRANGE(); // jedis.zincrby(KEY, getRandomInt(), VALUE + 10); // ZRANGE(); jedis.zincrby(KEY, 20, VALUE + 10); ZRANGE(); } /** * ZRANGE key start stop [WITHSCORES] * 返回有序集 key 中,指定區間內的成員。 * 其中成員的位置按 score 值遞增(從小到大)來排序。 * 具有相同 score 值的成員按字典序(lexicographical order )來排列。 * 如果你需要成員按 score 值遞減(從大到小)來排列,請使用 ZREVRANGE 命令。 * 下標引數 start 和 stop 都以 0 為底,也就是說,以 0 表示有序集第一個成員,以 1 表示有序集第二個成員,以此類推。 * 你也可以使用負數下標,以 -1 表示最後一個成員, -2 表示倒數第二個成員,以此類推。 * 超出範圍的下標並不會引起錯誤。 * 比如說,當 start 的值比有序集的最大下標還要大,或是 start > stop 時, ZRANGE 命令只是簡單地返回一個空列表。 * 另一方面,假如 stop 引數的值比有序集的最大下標還要大,那麼 Redis 將 stop 當作最大下標來處理。 * 可以通過使用 WITHSCORES 選項,來讓成員和它的 score 值一併返回,返回列表以 value1,score1, ..., valueN,scoreN 的格式表示。 * 客戶端庫可能會返回一些更復雜的資料型別,比如陣列、元組等。 * <p/> * ZREVRANGE key start stop [WITHSCORES] * 返回有序集 key 中,指定區間內的成員。 * 其中成員的位置按 score 值遞減(從大到小)來排列。 * 具有相同 score 值的成員按字典序的逆序(reverse lexicographical order)排列。 * 除了成員按 score 值遞減的次序排列這一點外, ZREVRANGE 命令的其他方面和 ZRANGE 命令一樣。 */ @Test public void ZRANGE() { // System.out.println(jedis.zrange(KEY, 0, -1)); Set<Tuple> tuples = jedis.zrangeWithScores(KEY, 0, -1); for (Tuple tuple : tuples) { System.out.println(tuple.getElement() + ":" + tuple.getScore()); } } /** * ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] * 返回有序集 key 中,所有 score 值介於 min 和 max 之間(包括等於 min 或 max )的成員。有序整合員按 score 值遞增(從小到大)次序排列。 * 具有相同 score 值的成員按字典序(lexicographical order)來排列(該屬性是有序集提供的,不需要額外的計算)。 * 可選的 LIMIT 引數指定返回結果的數量及區間(就像SQL中的 SELECT LIMIT offset, count ),注意當 offset 很大時,定位 offset 的操作可能需要遍歷整個有序集,此過程最壞複雜度為 O(N) 時間。 * 可選的 WITHSCORES 引數決定結果集是單單返回有序集的成員,還是將有序整合員及其 score 值一起返回。 * 該選項自 Redis 2.0 版本起可用。 * 區間及無限 * min 和 max 可以是 -inf 和 +inf ,這樣一來,你就可以在不知道有序集的最低和最高 score 值的情況下,使用 ZRANGEBYSCORE 這類命令。 * 預設情況下,區間的取值使用閉區間 (小於等於或大於等於),你也可以通過給引數前增加 ( 符號來使用可選的開區間 (小於或大於)。 * <p/> * ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] * 返回有序集 key 中, score 值介於 max 和 min 之間(預設包括等於 max 或 min )的所有的成員。有序整合員按 score 值遞減(從大到小)的次序排列。 * 具有相同 score 值的成員按字典序的逆序(reverse lexicographical order )排列。 * 除了成員按 score 值遞減的次序排列這一點外, ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一樣。 */ @Test public void ZRANGEBYSCORE() { System.out.println(jedis.zrangeByScore(KEY, 0, 100)); System.out.println(jedis.zrangeByScore(KEY, 0, 100, 8, 15)); System.out.println(jedis.zrangeByScore(KEY, "-inf", "+inf")); System.out.println(jedis.zrangeByScore(KEY, "-inf", "+inf", 8, 1)); Set<Tuple> tuples = jedis.zrangeByScoreWithScores(KEY, "-inf", "+inf", 8, 1); for (Tuple tuple : tuples) { System.out.println(tuple.getElement() + "=" + tuple.getScore()); } } /** * ZRANK key member * 返回有序集 key 中成員 member 的排名。其中有序整合員按 score 值遞增(從小到大)順序排列。 * 排名以 0 為底,也就是說, score 值最小的成員排名為 0 。 * 使用 ZREVRANK 命令可以獲得成員按 score 值遞減(從大到小)排列的排名。 * <p/> * ZREVRANK key member * 返回有序集 key 中成員 member 的排名。其中有序整合員按 score 值遞減(從大到小)排序。 * 排名以 0 為底,也就是說, score 值最大的成員排名為 0 。 * 使用 ZRANK 命令可以獲得成員按 score 值遞增(從小到大)排列的排名。 */ @Test public void ZRANK() { System.out.println(jedis.zrank(KEY, "layman56.0")); } /** * ZREM key member [member ...] * 移除有序集 key 中的一個或多個成員,不存在的成員將被忽略。 * 當 key 存在但不是有序集型別時,返回一個錯誤。 */ @Test public void ZREM() { ZRANGE(); jedis.zrem(KEY, "layman72.0", "layman77.0"); System.out.println("######################"); ZRANGE(); } /** * ZREMRANGEBYRANK key start stop * 移除有序集 key 中,指定排名(rank)區間內的所有成員。 * 區間分別以下標引數 start 和 stop 指出,包含 start 和 stop 在內。 * 下標引數 start 和 stop 都以 0 為底,也就是說,以 0 表示有序集第一個成員,以 1 表示有序集第二個成員,以此類推。 * 你也可以使用負數下標,以 -1 表示最後一個成員, -2 表示倒數第二個成員,以此類推。 */ @Test public void ZREMRANGEBYRANK() { ZRANGE(); jedis.zremrangeByRank(KEY, 0, 1); System.out.println("##################"); ZRANGE(); } /** * ZREMRANGEBYSCORE key min max * 移除有序集 key 中,所有 score 值介於 min 和 max 之間(包括等於 min 或 max )的成員。 * 自版本2.1.6開始, score 值等於 min 或 max 的成員也可以不包括在內,詳情請參見 ZRANGEBYSCORE 命令。 */ @Test public void ZREMRANGEBYSCORE() { ZRANGE(); jedis.zremrangeByScore(KEY, "53", "63");//刪除53<score<63 System.out.println("#####################"); ZRANGE(); } /** * ZSCORE key member * 返回有序集 key 中,成員 member 的 score 值。 * 如果 member 元素不是有序集 key 的成員,或 key 不存在,返回 nil 。 */ @Test public void ZSCORE() { System.out.println(jedis.zscore(KEY, "layman84.0")); } /** * ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] * 計算給定的一個或多個有序集的並集,其中給定 key 的數量必須以 numkeys 引數指定,並將該並集(結果集)儲存到 destination 。 * 預設情況下,結果集中某個成員的 score 值是所有給定集下該成員 score 值之 和 。 * WEIGHTS * 使用 WEIGHTS 選項,你可以為 每個 給定有序集 分別 指定一個乘法因子(multiplication factor), * 每個給定有序集的所有成員的 score 值在傳遞給聚合函式(aggregation function)之前都要先乘以該有序集的因子。 * 如果沒有指定 WEIGHTS 選項,乘法因子預設設定為 1 。 * AGGREGATE * 使用 AGGREGATE 選項,你可以指定並集的結果集的聚合方式。 * 預設使用的引數 SUM ,可以將所有集合中某個成員的 score 值之 和 作為結果集中該成員的 score 值;使用引數 MIN , * 可以將所有集合中某個成員的最小score值作為結果集中該成員的score值;而引數MAX則是將所有集合中某個成員的最大score值作為結果集中該成員的score值。 */ @Test public void ZUNIONSTORE() { ZADDForKey(KEY + 0); ZRANGE(); System.out.println("###############################"); System.out.println(jedis.zrange(KEY + 0, 0, -1)); ZParams zParams = new ZParams(); zParams.aggregate(ZParams.Aggregate.MAX); // zParams.weightsByDouble(1); jedis.zunionstore(KEY, zParams, KEY, KEY + 0); System.out.println("###############################"); System.out.println(jedis.zrange(KEY, 0, -1)); } /** * ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] * 計算給定的一個或多個有序集的交集,其中給定 key 的數量必須以 numkeys 引數指定,並將該交集(結果集)儲存到 destination 。 * 預設情況下,結果集中某個成員的 score 值是所有給定集下該成員 score 值之和. * 關於 WEIGHTS 和 AGGREGATE 選項的描述,參見 ZUNIONSTORE 命令。 */ @Test public void ZINTERSTORE() { System.out.println(jedis.zrange(KEY, 0, -1)); System.out.println("###############################"); ZParams zParams = new ZParams(); zParams.aggregate(ZParams.Aggregate.MIN); // zParams.weightsByDouble(1d); System.out.println(jedis.zrange(KEY + 0, 0, -1)); jedis.zinterstore(KEY, zParams, KEY, KEY + 0); System.out.println("###############################"); System.out.println(jedis.zrange(KEY, 0, -1)); } /** * ZRANGEBYLEX key min max [LIMIT offset count] * 當有序集合的所有成員都具有相同的分值時, 有序集合的元素會根據成員的字典序(lexicographical ordering)來進行排序, * 而這個命令則可以返回給定的有序集合鍵 key 中, 值介於 min 和 max 之間的成員。 * 如果有序集合裡面的成員帶有不同的分值, 那麼命令返回的結果是未指定的(unspecified)。 * 命令會使用 C 語言的 memcmp() 函式, 對集合中的每個成員進行逐個位元組的對比(byte-by-byte compare), 並按照從低到高的順序, 返回排序後的集合成員。 * 如果兩個字串有一部分內容是相同的話, 那麼命令會認為較長的字串比較短的字串要大。 * 可選的 LIMIT offset count 引數用於獲取指定範圍內的匹配元素 (就像 SQL 中的 SELECT LIMIT offset count 語句)。 需要注意的一點是, * 如果 offset 引數的值非常大的話, 那麼命令在返回結果之前, 需要先遍歷至 offset 所指定的位置, 這個操作會為命令加上最多 O(N) 複雜度。 * 如何指定範圍區間 * 合法的 min 和 max 引數必須包含 ( 或者 [ , 其中 ( 表示開區間(指定的值不會被包含在範圍之內), 而 [ 則表示閉區間(指定的值會被包含在範圍之內)。 * 特殊值 + 和 - 在 min 引數以及 max 引數中具有特殊的意義, 其中 + 表示正無限, 而 - 表示負無限。 因此, 向一個所有成員的分值都相同的有序集合傳送命令 * ZRANGEBYLEX <zset> - + , 命令將返回有序集合中的所有元素。 */ @Test public void ZRANGEBYLEX() { /** * redis> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g (integer) 7 redis> ZRANGEBYLEX myzset - [c 1) "a" 2) "b" 3) "c" redis> ZRANGEBYLEX myzset - (c 1) "a" 2) "b" redis> ZRANGEBYLEX myzset [aaa (g 1) "b" 2) "c" 3) "d" 4) "e" 5) "f" */ ZRANGE(); System.out.println(jedis.zrangeByLex(KEY, "-", "+")); System.out.println(jedis.zrangeByLex(KEY, "-", "+", 1, 2)); } /** * ZLEXCOUNT key min max * 對於一個所有成員的分值都相同的有序集合鍵 key 來說, 這個命令會返回該集合中, 成員介於 min 和 max 範圍內的元素數量。 * 這個命令的 min 引數和 max 引數的意義和 ZRANGEBYLEX 命令的 min 引數和 max 引數的意義一樣。 */ @Test public void ZLEXCOUNT() { System.out.println(jedis.zlexcount(KEY, "-", "+")); } /** * ZREMRANGEBYLEX key min max * 對於一個所有成員的分值都相同的有序集合鍵 key 來說, 這個命令會移除該集合中, 成員介於 min 和 max 範圍內的所有元素。 * 這個命令的 min 引數和 max 引數的意義和 ZRANGEBYLEX 命令的 min 引數和 max 引數的意義一樣。 */ @Test public void ZREMRANGEBYLEX() { ZRANGE(); jedis.zremrangeByLex(KEY, "-", "+"); System.out.println("#################"); ZRANGE(); } private int getRandomInt() { return new Random().nextInt(100); } private void ZADDForKey(String key) { if (StringUtils.isEmpty(key)) { key = KEY; } Map<String, Double> sourceMember = new HashMap<String, Double>(); for (int i = 0; i < 3; i++) { double score = getRandomInt(); sourceMember.put(VALUE + score, score); } jedis.zadd(key, sourceMember); } }