Redis:查找一个范围和一个无序集合的交集

4

我有一个有序集合——这些项目是我通过' redis ' gem进行评分并添加到我的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命令时,会出现以下错误:"Could not connect to Redis at 127.0.0.1:6379: Connection refused." 升级到redis 2.4.13后,这个错误消失了。 - Mark Swardstrom
另外需要注意的是,在redis 2.4.13中,我无法在zinterstore中使用sunonstore的结果。再次升级后问题得到解决。现在在版本2.6.10上一切正常运行。 - Mark Swardstrom
2个回答

3

关键点是 sorted set 命令也接受普通集合作为参数。因此,您可以先将其与集合相交,然后使用普通的范围命令根据分数进行过滤。

示例:

# 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

感谢您关于删除临时存储的提示。 - Mark Swardstrom

2

我不知道先获得范围,后交叉的方法。但是,你可以做一个集合的交集,然后再进行范围操作:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接