2012-07-29 16 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

相关问题