【问题标题】:Redis: Find the intersection of a range and an unordered setRedis:查找范围和无序集的交集
【发布时间】:2013-02-12 19:22:28
【问题描述】:

我有一个有序的集合 - 我通过 gem 'redis' 评分并添加到我的 redis 数据库中的项目,如下所示:

Item.each { |item|
  $redis.zadd("scores", item.score, item.id)
}

还有一组带有基于标签 id 的键的项目。

Tag.each { |tag|
  tag.items.each { |item|
     $redis.sadd("tag_#{tag.id}", item.id)
  }
}

我正在尝试获取得分为 x 或以上 的所有项目,并将其与具有特定标签的所有项目相交。我不需要对结果进行排序。我不确定我是否需要首先使用有序集,但这似乎是一种存储和检索结果的有效方式。

使用 Redis 查找范围和集合的交集的最佳方法是什么?

【问题讨论】:

  • 我在使用 Redis 2.2.5 时遇到了问题。当我尝试调用 zinterstore 命令时,我会收到此错误。 “无法在 127.0.0.1:6379 连接到 Redis:连接被拒绝。”升级到redis 2.4.13后,这个错误就消失了。
  • 另一个注意事项 - 在 redis 2.4.13 上,我无法在 zinterstore 中使用 sunionstore 的结果。再次升级解决了这个问题。现在在 2.6.10 版本上一切正常。

标签: ruby-on-rails redis


【解决方案1】:

关键是排序集命令也接受普通集作为参数。所以可以先与集合相交,然后使用正常范围命令根据分数进行过滤。

示例:

# Populate some sorted set and set
./redis-cli zadd scores 1 a 2 b 3 c 4 d 5 e 6 f 7 g 8 h
(integer) 8
./redis-cli sadd tag_1 a c d g h
(integer) 5

# Here you need to use a weight clause to avoid altering the score
./redis-cli zinterstore res 2 scores tag_1 weights 1 0
(integer) 5

# Now fetch the expected items (here we want items with score >= 4)
./redis-cli zrangebyscore res 4 +inf withscores
1) "d"
2) "4"
3) "g"
4) "7"
5) "h"
6) "8"

# Finally drop the temporary result
./redis-cli del res
(integer) 1

【讨论】:

  • 感谢有关删除临时存储的提示
【解决方案2】:

我不知道先获取范围,然后再相交的方法。但是,您可以做的是使集合相交,然后做范围:

ZINTERSTORE items_with_tag_foo 2 items tag_foo AGGREGATE MAX
ZRANGEBYSCORE items_with_tag_foo 17 +inf

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 2016-04-14
    • 2021-02-05
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多