Class: Redis::SortedSet

Inherits:
BaseObject show all
Includes:
Helpers::CoreCommands
Defined in:
lib/redis/sorted_set.rb

Overview

Class representing a sorted set.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::CoreCommands

#exists?, #expire, #expireat, #marshal, #move, #persist, #rename, #renamenx, #sort, #ttl, #type, #unmarshal

Methods inherited from BaseObject

#allow_expiration, #as_json, #initialize, #redis, #set_expiration, #to_hash, #to_json

Constructor Details

This class inherits a constructor from Redis::BaseObject

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



13
14
15
# File 'lib/redis/sorted_set.rb', line 13

def key
  @key
end

#optionsObject (readonly)

Returns the value of attribute options.



13
14
15
# File 'lib/redis/sorted_set.rb', line 13

def options
  @options
end

Instance Method Details

#==(x) ⇒ Object



282
283
284
# File 'lib/redis/sorted_set.rb', line 282

def ==(x)
  members == x
end

#[](index, length = nil) ⇒ Object Also known as: slice

Same functionality as Ruby arrays. If a single number is given, return just the element at that index using Redis: ZRANGE. Otherwise, return a range of values using Redis: ZRANGE.



46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/redis/sorted_set.rb', line 46

def [](index, length=nil)
  if index.is_a? Range
    range(index.first, index.max)
  elsif length
    case length <=> 0
    when 1  then range(index, index + length - 1)
    when 0  then []
    when -1 then nil  # Ruby does this (a bit weird)
    end
  else
    result = score(index) || 0 # handles a nil score
  end
end

#[]=(member, score) ⇒ Object

How to add values using a sorted set. The key is the member, eg, “Peter”, and the value is the score, eg, 163. So:

num_posts['Peter'] = 163


18
19
20
# File 'lib/redis/sorted_set.rb', line 18

def []=(member, score)
  add(member, score)
end

#add(member, score) ⇒ Object

Add a member and its corresponding value to Redis. Note that the arguments to this are flipped; the member comes first rather than the score, since the member is the unique item (not the score).



25
26
27
28
29
# File 'lib/redis/sorted_set.rb', line 25

def add(member, score)
  allow_expiration do
    redis.zadd(key, score, marshal(member))
  end
end

#at(index) ⇒ Object

Return the value at the given index. Can also use familiar list syntax. Redis: ZRANGE



292
293
294
# File 'lib/redis/sorted_set.rb', line 292

def at(index)
  range(index, index).first
end

#decrement(member, by = 1) ⇒ Object Also known as: decr, decrby

Convenience to calling increment() with a negative number.



191
192
193
194
195
# File 'lib/redis/sorted_set.rb', line 191

def decrement(member, by=1)
  allow_expiration do
    zincrby(member, -by)
  end
end

#delete(value) ⇒ Object

Delete the value from the set. Redis: ZREM



162
163
164
165
166
# File 'lib/redis/sorted_set.rb', line 162

def delete(value)
  allow_expiration do
    redis.zrem(key, marshal(value))
  end
end

#delete_if(&block) ⇒ Object

Delete element if it matches block

Raises:

  • (ArgumentError)


169
170
171
172
173
174
175
176
177
178
# File 'lib/redis/sorted_set.rb', line 169

def delete_if(&block)
  raise ArgumentError, "Missing block to SortedSet#delete_if" unless block_given?
  res = false
  redis.zrange(key, 0, -1).each do |m|
    if block.call(unmarshal(m))
      res = redis.zrem(key, m)
    end
  end
  res
end

#difference(*sets) ⇒ Object Also known as: diff, ^, -

Return the difference vs another set. Can pass it either another set object or set name. Also available as ^ or - which is a bit cleaner:

members_difference = set1 ^ set2
members_difference = set1 - set2

If you want to specify multiple sets, you must use difference:

members_difference = set1.difference(set2, set3, set4)
members_difference = set1.diff(set2, set3, set4)

Redis: SDIFF



264
265
266
# File 'lib/redis/sorted_set.rb', line 264

def difference(*sets)
  redis.zdiff(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
end

#diffstore(name, *sets) ⇒ Object

Calculate the diff and store it in Redis as name. Returns the number of elements in the stored union. Redis: SDIFFSTORE



273
274
275
# File 'lib/redis/sorted_set.rb', line 273

def diffstore(name, *sets)
  redis.zdiffstore(name, key, *keys_from_objects(sets))
end

#empty?Boolean

Returns true if the set has no members. Redis: SCARD == 0

Returns:

  • (Boolean)


278
279
280
# File 'lib/redis/sorted_set.rb', line 278

def empty?
  length == 0
end

#firstObject

Return the first element in the list. Redis: ZRANGE(0)



297
298
299
# File 'lib/redis/sorted_set.rb', line 297

def first
  at(0)
end

#increment(member, by = 1) ⇒ Object Also known as: incr, incrby

Increment the rank of that member atomically and return the new value. This method is aliased as incr() for brevity. Redis: ZINCRBY



182
183
184
185
186
# File 'lib/redis/sorted_set.rb', line 182

def increment(member, by=1)
  allow_expiration do
    zincrby(member, by)
  end
end

#intersection(*sets) ⇒ Object Also known as: intersect, inter, &

Return the intersection with another set. Can pass it either another set object or set name. Also available as & which is a bit cleaner:

members_in_both = set1 & set2

If you want to specify multiple sets, you must use intersection:

members_in_all = set1.intersection(set2, set3, set4)
members_in_all = set1.inter(set2, set3, set4)  # alias

Redis: SINTER



210
211
212
# File 'lib/redis/sorted_set.rb', line 210

def intersection(*sets)
  redis.zinter(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
end

#interstore(name, *sets) ⇒ Object

Calculate the intersection and store it in Redis as name. Returns the number of elements in the stored intersection. Redis: SUNIONSTORE



219
220
221
222
223
224
# File 'lib/redis/sorted_set.rb', line 219

def interstore(name, *sets)
  allow_expiration do
    opts = sets.last.is_a?(Hash) ? sets.pop : {}
    redis.zinterstore(key_from_object(name), keys_from_objects([self] + sets), opts)
  end
end

#lastObject

Return the last element in the list. Redis: ZRANGE(-1)



302
303
304
# File 'lib/redis/sorted_set.rb', line 302

def last
  at(-1)
end

#lengthObject Also known as: size

The number of members in the set. Aliased as size. Redis: ZCARD



307
308
309
# File 'lib/redis/sorted_set.rb', line 307

def length
  redis.zcard(key)
end

#member?(value) ⇒ Boolean

Return a boolean indicating whether value is a member.

Returns:

  • (Boolean)


318
319
320
# File 'lib/redis/sorted_set.rb', line 318

def member?(value)
  !redis.zscore(key, marshal(value)).nil?
end

#members(options = {}) ⇒ Object Also known as: value

Return all members of the sorted set with their scores. Extremely CPU-intensive. Better to use a range instead.



92
93
94
# File 'lib/redis/sorted_set.rb', line 92

def members(options={})
  range(0, -1, options) || []
end

#merge(values) ⇒ Object Also known as: add_all

Add a list of members and their corresponding value (or a hash mapping values to scores) to Redis. Note that the arguments to this are flipped; the member comes first rather than the score, since the member is the unique item (not the score).



35
36
37
38
39
40
# File 'lib/redis/sorted_set.rb', line 35

def merge(values)
  allow_expiration do
    vals = values.map{|v,s| [s, marshal(v)] }
    redis.zadd(key, vals)
  end
end

#range(start_index, end_index, options = {}) ⇒ Object

Return a range of values from start_index to end_index. Can also use the familiar list Ruby syntax. Redis: ZRANGE



99
100
101
102
103
104
105
# File 'lib/redis/sorted_set.rb', line 99

def range(start_index, end_index, options={})
  if options[:withscores] || options[:with_scores]
    redis.zrange(key, start_index, end_index, :with_scores => true).map{|v,s| [unmarshal(v), s] }
  else
    redis.zrange(key, start_index, end_index).map{|v| unmarshal(v) }
  end
end

#range_size(min, max) ⇒ Object

The number of members within a range of scores. Redis: ZCOUNT



313
314
315
# File 'lib/redis/sorted_set.rb', line 313

def range_size(min, max)
  redis.zcount(key, min, max)
end

#rangebyscore(min, max, options = {}) ⇒ Object

Return the all the elements in the sorted set at key with a score between min and max (including elements with score equal to min or max). Options:

:count, :offset - passed to LIMIT
:withscores     - if true, scores are returned as well

Redis: ZRANGEBYSCORE



121
122
123
124
125
126
127
128
# File 'lib/redis/sorted_set.rb', line 121

def rangebyscore(min, max, options={})
  args = {}
  args[:limit] = [options[:offset] || 0, options[:limit] || options[:count]] if
            options[:offset] || options[:limit] || options[:count]
  args[:with_scores] = true if options[:withscores] || options[:with_scores]

  redis.zrangebyscore(key, min, max, args).map{|v| unmarshal(v) }
end

#rank(member) ⇒ Object

Return the rank of the member in the sorted set, with scores ordered from low to high. revrank returns the rank with scores ordered from high to low. When the given member does not exist in the sorted set, nil is returned. The returned rank (or index) of the member is 0-based for both commands



74
75
76
77
78
79
80
# File 'lib/redis/sorted_set.rb', line 74

def rank(member)
  if n = redis.zrank(key, marshal(member))
    n.to_i
  else
    nil
  end
end

#remrangebyrank(min, max) ⇒ Object

Remove all elements in the sorted set at key with rank between start and end. Start and end are 0-based with rank 0 being the element with the lowest score. Both start and end can be negative numbers, where they indicate offsets starting at the element with the highest rank. For example: -1 is the element with the highest score, -2 the element with the second highest score and so forth. Redis: ZREMRANGEBYRANK



151
152
153
# File 'lib/redis/sorted_set.rb', line 151

def remrangebyrank(min, max)
  redis.zremrangebyrank(key, min, max)
end

#remrangebyscore(min, max) ⇒ Object

Remove all the elements in the sorted set at key with a score between min and max (including elements with score equal to min or max). Redis: ZREMRANGEBYSCORE



157
158
159
# File 'lib/redis/sorted_set.rb', line 157

def remrangebyscore(min, max)
  redis.zremrangebyscore(key, min, max)
end

#revrange(start_index, end_index, options = {}) ⇒ Object

Return a range of values from start_index to end_index in reverse order. Redis: ZREVRANGE



108
109
110
111
112
113
114
# File 'lib/redis/sorted_set.rb', line 108

def revrange(start_index, end_index, options={})
  if options[:withscores] || options[:with_scores]
    redis.zrevrange(key, start_index, end_index, :with_scores => true).map{|v,s| [unmarshal(v), s] }
  else
    redis.zrevrange(key, start_index, end_index).map{|v| unmarshal(v) }
  end
end

#revrangebyscore(max, min, options = {}) ⇒ Object

Returns all the elements in the sorted set at key with a score between max and min (including elements with score equal to max or min). In contrary to the default ordering of sorted sets, for this command the elements are considered to be ordered from high to low scores. Options:

:count, :offset - passed to LIMIT
:withscores     - if true, scores are returned as well

Redis: ZREVRANGEBYSCORE



137
138
139
140
141
142
143
144
# File 'lib/redis/sorted_set.rb', line 137

def revrangebyscore(max, min, options={})
  args = {}
  args[:limit] = [options[:offset] || 0, options[:limit] || options[:count]] if
            options[:offset] || options[:limit] || options[:count]
  args[:with_scores] = true if options[:withscores] || options[:with_scores]

  redis.zrevrangebyscore(key, max, min, args).map{|v| unmarshal(v) }
end

#revrank(member) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/redis/sorted_set.rb', line 82

def revrank(member)
  if n = redis.zrevrank(key, marshal(member))
    n.to_i
  else
    nil
  end
end

#score(member) ⇒ Object

Return the score of the specified element of the sorted set at key. If the specified element does not exist in the sorted set, or the key does not exist at all, nil is returned. Redis: ZSCORE.



64
65
66
67
68
# File 'lib/redis/sorted_set.rb', line 64

def score(member)
  result = redis.zscore(key, marshal(member))

  result.to_f unless result.nil?
end

#to_sObject



286
287
288
# File 'lib/redis/sorted_set.rb', line 286

def to_s
  members.join(', ')
end

#union(*sets) ⇒ Object Also known as: |, +

Return the union with another set. Can pass it either another set object or set name. Also available as | and + which are a bit cleaner:

members_in_either = set1 | set2
members_in_either = set1 + set2

If you want to specify multiple sets, you must use union:

members_in_all = set1.union(set2, set3, set4)

Redis: SUNION



237
238
239
# File 'lib/redis/sorted_set.rb', line 237

def union(*sets)
  redis.zunion(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
end

#unionstore(name, *sets) ⇒ Object

Calculate the union and store it in Redis as name. Returns the number of elements in the stored union. Redis: SUNIONSTORE



245
246
247
248
249
250
# File 'lib/redis/sorted_set.rb', line 245

def unionstore(name, *sets)
  allow_expiration do
    opts = sets.last.is_a?(Hash) ? sets.pop : {}
    redis.zunionstore(key_from_object(name), keys_from_objects([self] + sets), opts)
  end
end