1. 程式人生 > >Jedis操作Redis--SortedSet型別

Jedis操作Redis--SortedSet型別

/**
 * 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);
    }
}