2012-07-29 43 views
5

考慮一個Redis的有序set具有以下成員:反向分頁通過一個Redis的有序集合

ZADD mySortedSet 11 "A" 
ZADD mySortedSet 21 "B" 
ZADD mySortedSet 32 "C" 
ZADD mySortedSet 46 "D" 
ZADD mySortedSet 53 "E" 
ZADD mySortedSet 68 "F" 
ZADD mySortedSet 72 "G" 
ZADD mySortedSet 82 "H" 
ZADD mySortedSet 94 "I" 
ZADD mySortedSet 104 "J" 
ZADD mySortedSet 113 "K" 

如果我想做分頁以相反的順序,從任意一個片,我可以這樣開始:

// Returns G, F, E, as expected. 
ZREVRANGEBYSCORE mySortedSet 72 (46 

現在,只知道我的上限是46,我可以在一組前3項,d,C和B,不知道這樣做勢必較低:

ZREVRANGEBYSCORE mySortedSet 46 -inf LIMIT 0, 3 

我的問題是,我怎麼才能得到集合中的下三個項目,J,I和H,只知道上限是72?

// Good start, returns K, J, I, H 
ZREVRANGEBYSCORE mySortedSet +inf (72 

// Returns K, J, I, due to the offset of 0. I don't know what the correct offset is because it's from the start of the range, not the end. 
ZREVRANGEBYSCORE mySortedSet +inf (72 LIMIT 0, 3 

我認爲我想要的是一個負偏移量,我認爲它不被支持。

// Would return J, I, H, but actually returns an empty set. 
ZREVRANGEBYSCORE mySortedSet +inf (72 LIMIT -1, 3 

我可以用一個前進檔僞造它,然後扭轉這些項目,但我正在尋找一個本地Redis的解決方案,如果存在的話。

// Returns H, I, J - the items I want, but reversed. 
ZRANGEBYSCORE mySortedSet (72 +inf LIMIT 0, 3 

任何想法?

要清楚,我知道有ZRANGE和ZREVRANGE,但在這個查詢配置文件中,我不會知道實際的索引,只是得分。

+0

沒有簡單的方法來做到這一點。我看到三種選擇。 (1)在客戶端反向(2)使用LUA反向(3)使用ZCOUNT知道元素的數量並從中減去作爲負指數的替代。 – seppo0010 2012-07-29 23:50:00

+0

嘿seppo0010,謝謝你的輸入。我目前正在做1,只是想看看是否有更好的方法。不是這樣的LUA腳本的粉絲,但肯定會考慮ZCOUNT方法,因爲查詢在MULTI內部運行,所以它將保持原子性。 – majelbstoat 2012-07-30 03:31:28

回答

1

得到一個元素的等級,然後通過索引工作很簡單。假定該提供給您的應用程序的唯一輸入是72和46的初始分數範圍,你可以這樣做:

redis 127.0.0.1:6379> ZREVRANGEBYSCORE mySortedSet 72 (46 
1) "G" 
2) "F" 
3) "E" 
redis 127.0.0.1:6379> ZREVRANK mySortedSet G 
(integer) 4 
redis 127.0.0.1:6379> ZREVRANGE mySortedSet 1 3 
1) "J" 
2) "I" 
3) "H" 
redis 127.0.0.1:6379> 

唯一的額外調用是O(日誌(N))ZREVRANK調用。從那裏開始,爲了獲得您感興趣的範圍的新索引,並且ZREVRANGE可以獲得您想要的值,這有點客戶端數學問題。

我在Redis 2.6rc5上測試了它,但它應該可以在2.0以上的任何版本上運行。

+0

謝謝,這看起來也是一種合理的方法。唯一的問題是我不得不把這個請求分解成多個調用,否則編寫一個LUA腳本來處理計算中間範圍。取決於數據的概況,O(log(N)),其中N(該集合的基數很大)也可能比簡單地顛倒「正向有序範圍」更耗費時間,該「正向有序範圍」將具有M,即計數的返回。 – majelbstoat 2012-07-31 20:40:03

+0

是的,取決於你的數據的大小,抓住它並扭轉它可能會更好;不要忘記,你最終會支付你不使用的網絡傳輸成本。不幸的是,流水線並沒有給你帶來太多,因爲你需要中間值來構建後續的查詢。不知道你還沒有什麼其他的選項可以重新設計上游的東西來提供不同的輸入。 – 2012-07-31 23:20:17

相關問題