Redis: find intersection of range and unordered set

I have an ordered set - items that I have hammered in and added to my redis db via the "redis" gem like this:

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

      

And a set full of items with a key based on the tag id.

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

      

I am trying to get all elements with a score of x or higher and intersect with all elements that have a specific tag. I don't need the result to sort. I'm not sure if I need to use an ordered set in the first place, but it seems to be an efficient way to store and retrieve results.

What's the best way to find the intersection of range and set using Redis?

+3


source to share


2 answers


The key point is that sorted set commands also take normal set as parameters. So you can first intersect with the set and then use the normal range commands to filter based on the score.

Example:



# 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


source


I don't know how to get the range first, and cross it later. However, you can do intersection of sets and then do range:



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

      

+1


source







All Articles