pagination - 通过 Redis 排序集反向分页

标签 pagination redis sortedset

考虑具有以下成员的 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

我的问题是,如何只知道上限是 72,才能按顺序获得集合中接下来的 3 项 J、I 和 H?

// 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,但在这个查询配置文件中,我不知道实际索引,只知道分数。

最佳答案

获得一个元素的排名,然后通过索引进行处理是微不足道的。假设您的应用程序唯一可用的输入是 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(log(N)) ZREVRANK 调用。从那里开始,获取您感兴趣的范围的新索引和 ZREVRANGE 获取您想要的值需要一些客户端数学。

我在 Redis 2.6rc5 上测试过它,但它应该适用于 2.0 以上的任何版本。

关于pagination - 通过 Redis 排序集反向分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11713001/

相关文章:

php - 用于自定义集合的 Magento 分页

Github API 分页限制

node.js - Redis 消息的异步操作

redis - redis中zadd的时间复杂度

redis zrank : Floating-Point Numbers May Lose Precision

java - 如何获取 SortedSet 的下一个元素?

performance - 像 sphinx 一样在ElasticSearch中分页结果

java - 如何在 Firestore 查询的组合任务中获取最后一个可见的 DocumentSnapshot?

node.js - 带有nodejs异步请求的redis中的for循环

redis - 如何在重启前通过 capistrano 删除 sidekiq 特定的 redis 缓存