【问题标题】:Reverse Pagination Through A Redis Sorted Set通过 Redis 排序集进行反向分页
【发布时间】:2012-07-29 21:12:30
【问题描述】:

考虑一个包含以下成员的 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,但是在这个查询配置文件中,我不知道实际的索引,只知道分数。

【问题讨论】:

  • 没有简单的方法可以做到这一点。我看到三个选项。 (1) 在您的客户端上进行反向 (2) 使用 LUA 进行反向 (3) 使用 ZCOUNT 来了解元素的数量并从中减去以替换负索引。
  • 嘿 seppo0010,感谢您的意见。我目前正在做1,只是想看看是否有更好的方法。不喜欢这样的 LUA 脚本,但肯定会考虑 ZCOUNT 方法,因为查询在 MULTI 中运行,因此它将保持原子性。

标签: pagination redis sortedset


【解决方案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(log(N)) ZREVRANK 调用。从那里,获取您感兴趣的范围的新索引和ZREVRANGE 获取您想要的值是一些客户端数学运算。

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

【讨论】:

  • 谢谢,这看起来也是一种合理的方法。唯一的问题是我必须将请求分解为多个调用,或者编写一个 LUA 脚本来处理计算中间范围。根据数据的配置文件,O(log(N)),其中 N,集合的基数很大,也可能比简单地反转“前向排序范围”更耗时,后者将具有 M,计数返回的。
  • 是的,根据数据的大小,获取所有数据并反转它可能会更好;但是不要忘记,您最终会为不使用的东西支付网络传输费用。不幸的是,流水线在这里并没有给您带来太多好处,因为您需要中间值来构建后续查询。不确定除了重新设计上游的东西以提供不同的输入之外,您还有哪些其他选择。
猜你喜欢
  • 2019-09-16
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多