Class: Familia::SortedSet
- Includes:
- DataType::CollectionBase
- Defined in:
- lib/familia/data_type/types/sorted_set.rb
Instance Attribute Summary collapse
-
#features_enabled ⇒ Object
included
from Features
readonly
Returns the value of attribute features_enabled.
- #logical_database(val = nil) ⇒ Object included from DataType::ClassMethods
-
#parent ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute parent.
-
#prefix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute prefix.
-
#suffix ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute suffix.
-
#uri(val = nil) ⇒ Object
included
from DataType::ClassMethods
Returns the value of attribute uri.
Attributes included from Settings
#current_key_version, #default_expiration, #delim, #encryption_keys, #encryption_personalization, #logical_database, #prefix, #schema_path, #schema_validator, #schemas, #strict_write_order, #suffix, #transaction_mode
Instance Method Summary collapse
-
#<<(val) ⇒ Integer
Adds a new element to the sorted set with the current timestamp as the score.
-
#[]=(val, score) ⇒ Object
NOTE: The argument order is the reverse of #add.
-
#add(val, score = nil, nx: false, xx: false, gt: false, lt: false, ch: false) ⇒ Boolean
(also: #add_element)
Adds an element to the sorted set with an optional score and ZADD options.
- #at(idx) ⇒ Object
- #collectraw ⇒ Object
- #decrement(val, by = 1) ⇒ Object (also: #decr, #decrby)
-
#diff(*other_sets, withscores: false) ⇒ Array
Returns the difference between this sorted set and other sorted sets.
-
#diffstore(destination, *other_sets) ⇒ Integer
Stores the difference of sorted sets into a destination key.
-
#each(since: nil, batch_size: 100, **kwargs) {|member| ... } ⇒ Enumerator, self
Iterates over members of the sorted set.
- #eachraw ⇒ Object
- #eachraw_with_index ⇒ Object
-
#element_count ⇒ Integer
(also: #size, #length, #count)
Returns the number of elements in the sorted set.
- #empty? ⇒ Boolean
-
#first ⇒ Object
Return the first element in the list.
- #increment(val, by = 1) ⇒ Object (also: #incr, #incrby)
-
#inter(*other_sets, weights: nil, aggregate: nil, withscores: false) ⇒ Array
Returns the intersection of this sorted set with other sorted sets.
-
#interstore(destination, *other_sets, weights: nil, aggregate: nil) ⇒ Integer
Stores the intersection of sorted sets into a destination key.
-
#last ⇒ Object
Return the last element in the list.
-
#lexcount(min, max) ⇒ Integer
Counts members in a lexicographical range.
- #member?(val) ⇒ Boolean (also: #include?)
- #members(count = -1,, opts = {}) ⇒ Object (also: #to_a, #all)
- #membersraw(count = -1,, opts = {}) ⇒ Object
-
#mscore(*members) ⇒ Array<Float, nil>
Gets scores for multiple members at once.
-
#popmax(count = 1) ⇒ Array?
Removes and returns the member(s) with the highest score(s).
-
#popmin(count = 1) ⇒ Array?
Removes and returns the member(s) with the lowest score(s).
-
#randmember(count = nil, withscores: false) ⇒ Object, ...
Returns random member(s) from the sorted set.
- #range(sidx, eidx, opts = {}) ⇒ Object
-
#rangebylex(min, max, limit: nil) ⇒ Array
Returns members in a lexicographical range (requires all members have same score).
-
#rangebyscore(sscore, escore, opts = {}) ⇒ Object
e.g.
- #rangebyscoreraw(sscore, escore, opts = {}) ⇒ Object
- #rangeraw(sidx, eidx, opts = {}) ⇒ Object
-
#rank(v) ⇒ Object
rank of member +v+ when ordered lowest to highest (starts at 0).
-
#remove_element(value) ⇒ Integer
(also: #remove)
Removes a member from the sorted set.
-
#remrangebylex(min, max) ⇒ Integer
Removes members in a lexicographical range.
- #remrangebyrank(srank, erank) ⇒ Object
- #remrangebyscore(sscore, escore) ⇒ Object
- #revmembers(count = -1,, opts = {}) ⇒ Object
- #revmembersraw(count = -1,, opts = {}) ⇒ Object
- #revrange(sidx, eidx, opts = {}) ⇒ Object
-
#revrangebylex(max, min, limit: nil) ⇒ Array
Returns members in reverse lexicographical range.
-
#revrangebyscore(sscore, escore, opts = {}) ⇒ Object
e.g.
- #revrangebyscoreraw(sscore, escore, opts = {}) ⇒ Object
- #revrangeraw(sidx, eidx, opts = {}) ⇒ Object
-
#revrank(v) ⇒ Object
rank of member +v+ when ordered highest to lowest (starts at 0).
-
#scan(cursor = 0, match: nil, count: nil) ⇒ Array
Iterates over members using cursor-based scanning.
- #score(val) ⇒ Object (also: #[])
-
#score_count(min, max) ⇒ Integer
(also: #zcount)
Counts members within a score range.
- #selectraw ⇒ Object
-
#union(*other_sets, weights: nil, aggregate: nil, withscores: false) ⇒ Array
Returns the union of this sorted set with other sorted sets.
-
#unionstore(destination, *other_sets, weights: nil, aggregate: nil) ⇒ Integer
Stores the union of sorted sets into a destination key.
-
#update(hsh = {}) ⇒ Integer
(also: #merge!)
Bulk-adds or updates multiple members in a single ZADD.
Methods included from DataType::CollectionBase
#collection_type?, #each_record
Methods included from Features::Autoloader
autoload_files, included, normalize_to_config_name
Methods included from DataType::Serialization
#deserialize_value, #deserialize_values, #deserialize_values_with_nil, #serialize_value
Methods included from DataType::DatabaseCommands
#current_expiration, #delete!, #echo, #exists?, #expire, #expireat, #move, #persist, #rename, #renamenx, #type
Methods included from DataType::Connection
Methods included from Connection::Behavior
#connect, #create_dbclient, #multi, #normalize_uri, #pipeline, #pipelined, #transaction, #uri=, #url, #url=
Methods included from Settings
#configure, #default_suffix, #pipelined_mode, #pipelined_mode=
Methods included from Base
add_feature, #as_json, #expired?, #expires?, find_feature, #generate_id, #to_json, #to_s, #ttl, #update_expiration, #uuid
Constructor Details
This class inherits a constructor from Familia::DataType
Instance Attribute Details
#features_enabled ⇒ Object (readonly) Originally defined in module Features
Returns the value of attribute features_enabled.
#logical_database(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
#parent ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute parent.
#prefix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute prefix.
#suffix ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute suffix.
#uri(val = nil) ⇒ Object Originally defined in module DataType::ClassMethods
Returns the value of attribute uri.
Instance Method Details
#<<(val) ⇒ Integer
This is a non-standard operation for sorted sets as it doesn't allow
specifying a custom score. Use add or []= for more control.
Adds a new element to the sorted set with the current timestamp as the score.
This method provides a convenient way to add elements to the sorted set without explicitly specifying a score. It uses the current Unix timestamp as the score, which effectively sorts elements by their insertion time.
38 39 40 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 38 def <<(val) add(val) end |
#[]=(val, score) ⇒ Object
NOTE: The argument order is the reverse of #add. We do this to more naturally align with how the [] and []= methods are used.
e.g. obj.metrics[VALUE] = SCORE obj.metrics[VALUE] # => SCORE
49 50 51 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 49 def []=(val, score) add val, score end |
#add(val, score = nil, nx: false, xx: false, gt: false, lt: false, ch: false) ⇒ Boolean Also known as: add_element
GT and LT options do NOT prevent adding new elements, they only affect update behavior for existing elements.
Default behavior (no options) adds new elements and updates existing ones unconditionally, matching standard Redis ZADD semantics.
INCR option is not supported. Use the increment method for ZINCRBY operations.
This method executes a Redis ZADD immediately, unlike scalar field setters which are deferred until save. If the parent object has unsaved scalar field changes, consider calling save first to avoid split-brain state.
Adds an element to the sorted set with an optional score and ZADD options.
This method supports Redis ZADD options for conditional adds and updates:
- NX: Only add new elements (don't update existing)
- XX: Only update existing elements (don't add new)
- GT: Only update if new score > current score
- LT: Only update if new score < current score
- CH: Return changed count (new + updated) instead of just new count
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 111 def add(val, score = nil, nx: false, xx: false, gt: false, lt: false, ch: false) warn_if_dirty! score ||= Familia.now # Validate mutual exclusivity (nx: nx, xx: xx, gt: gt, lt: lt) # Build options hash for redis gem opts = {} opts[:nx] = true if nx opts[:xx] = true if xx opts[:gt] = true if gt opts[:lt] = true if lt opts[:ch] = true if ch # Pass options to ZADD ret = if opts.empty? dbclient.zadd(dbkey, score, serialize_value(val)) else dbclient.zadd(dbkey, score, serialize_value(val), **opts) end update_expiration ret end |
#at(idx) ⇒ Object
403 404 405 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 403 def at(idx) range(idx, idx).first end |
#collectraw ⇒ Object
309 310 311 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 309 def collectraw(&) membersraw.collect(&) end |
#decrement(val, by = 1) ⇒ Object Also known as: decr, decrby
385 386 387 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 385 def decrement(val, by = 1) increment val, -by end |
#diff(*other_sets, withscores: false) ⇒ Array
Returns the difference between this sorted set and other sorted sets.
727 728 729 730 731 732 733 734 735 736 737 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 727 def diff(*other_sets, withscores: false) keys = [dbkey] + resolve_set_keys(other_sets) result = if withscores dbclient.zdiff(*keys, withscores: true) else dbclient.zdiff(*keys) end process_set_operation_result(result, withscores: withscores) end |
#diffstore(destination, *other_sets) ⇒ Integer
Stores the difference of sorted sets into a destination key.
745 746 747 748 749 750 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 745 def diffstore(destination, *other_sets) keys = [dbkey] + resolve_set_keys(other_sets) result = dbclient.zdiffstore(destination, keys) update_expiration result end |
#each(since: nil, batch_size: 100, **kwargs) {|member| ... } ⇒ Enumerator, self
The until: parameter uses Ruby keyword syntax. Since until is
a reserved word, it's accessed via **kwargs internally.
Score-cursor pagination: bounded queries paginate using the last seen score as the next exclusive minimum. This is O(n) total work, unlike offset-based LIMIT which is O(n²). However, members with identical scores may be skipped between pages. Use high-precision floats (e.g., Familia.now) for scores to avoid collisions.
Iterates over members of the sorted set.
When called with score bounds (since/until), uses ZRANGEBYSCORE for efficient range queries. Otherwise uses ZSCAN for memory-efficient iteration over large sets.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 261 def each(since: nil, batch_size: 100, **kwargs, &block) until_score = kwargs.delete(:until) raise ArgumentError, "unknown keyword(s): #{kwargs.keys.join(', ')}" if kwargs.any? return to_enum(:each, since: since, until: until_score, batch_size: batch_size) unless block # Convert Time objects to numeric scores since_score = since.is_a?(Time) ? since.to_f : since until_score_val = until_score.is_a?(Time) ? until_score.to_f : until_score if since_score || until_score_val # Score-cursor pagination: track last score, use exclusive bound for next page min = since_score || '-inf' max = until_score_val || '+inf' loop do # with_scores returns nested pairs: [["a", 1.0], ["b", 2.0]] pairs = rangebyscoreraw(min, max, limit: [0, batch_size], with_scores: true) break if pairs.empty? pairs.each do |raw_member, score| yield deserialize_value(raw_member) min = "(#{score}" # exclusive bound for next iteration end break if pairs.size < batch_size end else # Use ZSCAN for unbounded iteration (memory-efficient) cursor = 0 loop do new_cursor, pairs = scan(cursor, count: batch_size) pairs.each { |member, _score| block.call(member) } cursor = new_cursor break if cursor.zero? end end self end |
#eachraw ⇒ Object
301 302 303 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 301 def eachraw(&) membersraw.each(&) end |
#eachraw_with_index ⇒ Object
305 306 307 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 305 def eachraw_with_index(&) membersraw.each_with_index(&) end |
#element_count ⇒ Integer Also known as: size, length, count
Returns the number of elements in the sorted set
11 12 13 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 11 def element_count dbclient.zcard dbkey end |
#empty? ⇒ Boolean
18 19 20 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 18 def empty? element_count.zero? end |
#first ⇒ Object
Return the first element in the list. Redis: ZRANGE(0)
408 409 410 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 408 def first at(0) end |
#increment(val, by = 1) ⇒ Object Also known as: incr, incrby
377 378 379 380 381 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 377 def increment(val, by = 1) ret = dbclient.zincrby(dbkey, by, serialize_value(val)).to_f update_expiration ret end |
#inter(*other_sets, weights: nil, aggregate: nil, withscores: false) ⇒ Array
Returns the intersection of this sorted set with other sorted sets.
556 557 558 559 560 561 562 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 556 def inter(*other_sets, weights: nil, aggregate: nil, withscores: false) keys = [dbkey] + resolve_set_keys(other_sets) opts = build_set_operation_opts(weights: weights, aggregate: aggregate, withscores: withscores) result = dbclient.zinter(*keys, **opts) process_set_operation_result(result, withscores: withscores) end |
#interstore(destination, *other_sets, weights: nil, aggregate: nil) ⇒ Integer
Stores the intersection of sorted sets into a destination key.
709 710 711 712 713 714 715 716 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 709 def interstore(destination, *other_sets, weights: nil, aggregate: nil) keys = [dbkey] + resolve_set_keys(other_sets) opts = build_set_operation_opts(weights: weights, aggregate: aggregate) result = dbclient.zinterstore(destination, keys, **opts) update_expiration result end |
#last ⇒ Object
Return the last element in the list. Redis: ZRANGE(-1)
413 414 415 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 413 def last at(-1) end |
#lexcount(min, max) ⇒ Integer
Counts members in a lexicographical range.
613 614 615 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 613 def lexcount(min, max) dbclient.zlexcount(dbkey, min, max) end |
#member?(val) ⇒ Boolean Also known as: include?
189 190 191 192 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 189 def member?(val) Familia.trace :MEMBER, nil, "#{val}<#{val.class}>" if Familia.debug? !rank(val).nil? end |
#members(count = -1,, opts = {}) ⇒ Object Also known as: to_a, all
207 208 209 210 211 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 207 def members(count = -1, opts = {}) count -= 1 if count.positive? elements = membersraw count, opts deserialize_values(*elements) end |
#membersraw(count = -1,, opts = {}) ⇒ Object
215 216 217 218 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 215 def membersraw(count = -1, opts = {}) count -= 1 if count.positive? rangeraw 0, count, opts end |
#mscore(*members) ⇒ Array<Float, nil>
Gets scores for multiple members at once.
514 515 516 517 518 519 520 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 514 def mscore(*members) return [] if members.empty? serialized = members.map { |m| serialize_value(m) } result = dbclient.zmscore(dbkey, *serialized) result.map { |s| s&.to_f } end |
#popmax(count = 1) ⇒ Array?
Removes and returns the member(s) with the highest score(s).
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 465 def popmax(count = 1) warn_if_dirty! # Normalize explicit nil to the default so the structural dispatch below # behaves identically whether the arg is omitted or passed as nil. # redis-rb treats nil as count <= 1 and returns a flat pair. count = 1 if count.nil? result = dbclient.zpopmax(dbkey, count) return nil if result.nil? || result.empty? update_expiration # redis-rb returns a flat [member, score] pair when count <= 1, and a # nested [[member, score], ...] array when count > 1. Normalize by # inspecting the result's structure rather than relying on count alone, # so that a redis-rb version change or a member that serializes to an # array-like string cannot mislead the dispatch. if count == 1 pair = result.first.is_a?(Array) ? result.first : result [deserialize_value(pair[0]), pair[1].to_f] else result.map { |member, score| [deserialize_value(member), score.to_f] } end end |
#popmin(count = 1) ⇒ Array?
Removes and returns the member(s) with the lowest score(s).
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 429 def popmin(count = 1) warn_if_dirty! # Normalize explicit nil to the default so the structural dispatch below # behaves identically whether the arg is omitted or passed as nil. # redis-rb treats nil as count <= 1 and returns a flat pair. count = 1 if count.nil? result = dbclient.zpopmin(dbkey, count) return nil if result.nil? || result.empty? update_expiration # redis-rb returns a flat [member, score] pair when count <= 1, and a # nested [[member, score], ...] array when count > 1. Normalize by # inspecting the result's structure rather than relying on count alone, # so that a redis-rb version change or a member that serializes to an # array-like string cannot mislead the dispatch. if count == 1 pair = result.first.is_a?(Array) ? result.first : result [deserialize_value(pair[0]), pair[1].to_f] else result.map { |member, score| [deserialize_value(member), score.to_f] } end end |
#randmember(count = nil, withscores: false) ⇒ Object, ...
Returns random member(s) from the sorted set.
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 632 def randmember(count = nil, withscores: false) if count.nil? result = dbclient.zrandmember(dbkey) return nil if result.nil? deserialize_value(result) else result = if withscores dbclient.zrandmember(dbkey, count, withscores: true) else dbclient.zrandmember(dbkey, count) end return [] if result.nil? || result.empty? if withscores result.map { |member, score| [deserialize_value(member), score.to_f] } else deserialize_values(*result) end end end |
#range(sidx, eidx, opts = {}) ⇒ Object
317 318 319 320 321 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 317 def range(sidx, eidx, opts = {}) echo :range, Familia.pretty_stack(limit: 1) if Familia.debug elements = rangeraw(sidx, eidx, opts) deserialize_values(*elements) end |
#rangebylex(min, max, limit: nil) ⇒ Array
Returns members in a lexicographical range (requires all members have same score).
577 578 579 580 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 577 def rangebylex(min, max, limit: nil) result = dbclient.zrangebylex(dbkey, min, max, limit: limit) deserialize_values(*result) end |
#rangebyscore(sscore, escore, opts = {}) ⇒ Object
e.g. obj.metrics.rangebyscore (now-12.hours), now, :limit => [0, 10]
339 340 341 342 343 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 339 def rangebyscore(sscore, escore, opts = {}) echo :rangebyscore, Familia.pretty_stack(limit: 1) if Familia.debug elements = rangebyscoreraw(sscore, escore, opts) deserialize_values(*elements) end |
#rangebyscoreraw(sscore, escore, opts = {}) ⇒ Object
345 346 347 348 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 345 def rangebyscoreraw(sscore, escore, opts = {}) echo :rangebyscoreraw, Familia.pretty_stack(limit: 1) if Familia.debug dbclient.zrangebyscore(dbkey, sscore, escore, **opts) end |
#rangeraw(sidx, eidx, opts = {}) ⇒ Object
323 324 325 326 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 323 def rangeraw(sidx, eidx, opts = {}) # NOTE: Redis 5.x gem uses :with_scores (with underscore) dbclient.zrange(dbkey, sidx, eidx, **opts) end |
#rank(v) ⇒ Object
rank of member +v+ when ordered lowest to highest (starts at 0)
196 197 198 199 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 196 def rank(v) ret = dbclient.zrank dbkey, serialize_value(v) ret&.to_i end |
#remove_element(value) ⇒ Integer Also known as: remove
Removes a member from the sorted set
394 395 396 397 398 399 400 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 394 def remove_element(value) warn_if_dirty! Familia.trace :REMOVE_ELEMENT, nil, "#{value}<#{value.class}>" if Familia.debug? ret = dbclient.zrem dbkey, serialize_value(value) update_expiration ret end |
#remrangebylex(min, max) ⇒ Integer
Removes members in a lexicographical range.
600 601 602 603 604 605 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 600 def remrangebylex(min, max) warn_if_dirty! result = dbclient.zremrangebylex(dbkey, min, max) update_expiration result end |
#remrangebyrank(srank, erank) ⇒ Object
363 364 365 366 367 368 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 363 def remrangebyrank(srank, erank) warn_if_dirty! ret = dbclient.zremrangebyrank dbkey, srank, erank update_expiration ret end |
#remrangebyscore(sscore, escore) ⇒ Object
370 371 372 373 374 375 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 370 def remrangebyscore(sscore, escore) warn_if_dirty! ret = dbclient.zremrangebyscore dbkey, sscore, escore update_expiration ret end |
#revmembers(count = -1,, opts = {}) ⇒ Object
220 221 222 223 224 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 220 def revmembers(count = -1, opts = {}) count -= 1 if count.positive? elements = revmembersraw count, opts deserialize_values(*elements) end |
#revmembersraw(count = -1,, opts = {}) ⇒ Object
226 227 228 229 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 226 def revmembersraw(count = -1, opts = {}) count -= 1 if count.positive? revrangeraw 0, count, opts end |
#revrange(sidx, eidx, opts = {}) ⇒ Object
328 329 330 331 332 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 328 def revrange(sidx, eidx, opts = {}) echo :revrange, Familia.pretty_stack(limit: 1) if Familia.debug elements = revrangeraw(sidx, eidx, opts) deserialize_values(*elements) end |
#revrangebylex(max, min, limit: nil) ⇒ Array
Returns members in reverse lexicographical range.
589 590 591 592 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 589 def revrangebylex(max, min, limit: nil) result = dbclient.zrevrangebylex(dbkey, max, min, limit: limit) deserialize_values(*result) end |
#revrangebyscore(sscore, escore, opts = {}) ⇒ Object
e.g. obj.metrics.revrangebyscore (now-12.hours), now, :limit => [0, 10]
351 352 353 354 355 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 351 def revrangebyscore(sscore, escore, opts = {}) echo :revrangebyscore, Familia.pretty_stack(limit: 1) if Familia.debug elements = revrangebyscoreraw(sscore, escore, opts) deserialize_values(*elements) end |
#revrangebyscoreraw(sscore, escore, opts = {}) ⇒ Object
357 358 359 360 361 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 357 def revrangebyscoreraw(sscore, escore, opts = {}) echo :revrangebyscoreraw, Familia.pretty_stack(limit: 1) if Familia.debug opts[:with_scores] = true if opts[:withscores] dbclient.zrevrangebyscore(dbkey, sscore, escore, **opts) end |
#revrangeraw(sidx, eidx, opts = {}) ⇒ Object
334 335 336 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 334 def revrangeraw(sidx, eidx, opts = {}) dbclient.zrevrange(dbkey, sidx, eidx, **opts) end |
#revrank(v) ⇒ Object
rank of member +v+ when ordered highest to lowest (starts at 0)
202 203 204 205 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 202 def revrank(v) ret = dbclient.zrevrank dbkey, serialize_value(v) ret&.to_i end |
#scan(cursor = 0, match: nil, count: nil) ⇒ Array
Iterates over members using cursor-based scanning.
673 674 675 676 677 678 679 680 681 682 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 673 def scan(cursor = 0, match: nil, count: nil) opts = {} opts[:match] = match if match opts[:count] = count if count new_cursor, result = dbclient.zscan(dbkey, cursor, **opts) members = result.map { |member, score| [deserialize_value(member), score.to_f] } [new_cursor.to_i, members] end |
#score(val) ⇒ Object Also known as: []
183 184 185 186 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 183 def score(val) ret = dbclient.zscore dbkey, serialize_value(val) ret&.to_f end |
#score_count(min, max) ⇒ Integer Also known as: zcount
Counts members within a score range.
501 502 503 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 501 def score_count(min, max) dbclient.zcount(dbkey, min, max) end |
#selectraw ⇒ Object
313 314 315 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 313 def selectraw(&) membersraw.select(&) end |
#union(*other_sets, weights: nil, aggregate: nil, withscores: false) ⇒ Array
Returns the union of this sorted set with other sorted sets.
538 539 540 541 542 543 544 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 538 def union(*other_sets, weights: nil, aggregate: nil, withscores: false) keys = [dbkey] + resolve_set_keys(other_sets) opts = build_set_operation_opts(weights: weights, aggregate: aggregate, withscores: withscores) result = dbclient.zunion(*keys, **opts) process_set_operation_result(result, withscores: withscores) end |
#unionstore(destination, *other_sets, weights: nil, aggregate: nil) ⇒ Integer
Stores the union of sorted sets into a destination key.
692 693 694 695 696 697 698 699 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 692 def unionstore(destination, *other_sets, weights: nil, aggregate: nil) keys = [dbkey] + resolve_set_keys(other_sets) opts = build_set_operation_opts(weights: weights, aggregate: aggregate) result = dbclient.zunionstore(destination, keys, **opts) update_expiration result end |
#update(hsh = {}) ⇒ Integer Also known as: merge!
Unlike single-value #add, scores are required: this bulk path does not default a missing score to Familia.now. A non-Numeric score (e.g. nil) raises ArgumentError rather than surfacing a low-level client error.
Like #add, this executes immediately (not deferred) and cascades expiration. Empty input is a no-op returning 0.
Bulk-adds or updates multiple members in a single ZADD.
Mirrors HashKey#update/merge! -- the established Familia pattern for bulk-setting keyed collections. A sorted set is member => score, the same pair shape as HashKey's field => value, so it takes a Hash rather than the variadic splat used by the value-only UnsortedSet/ListKey.
Issues exactly one ZADD instead of one round-trip per member, which is what makes populating a large sorted set fast.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/familia/data_type/types/sorted_set.rb', line 165 def update(hsh = {}) warn_if_dirty! raise ArgumentError, 'Argument to bulk add must be a hash' unless hsh.is_a?(Hash) return 0 if hsh.empty? pairs = hsh.map do |member, score| unless score.is_a?(Numeric) raise ArgumentError, "SortedSet#update score for #{member.inspect} must be Numeric, got #{score.class}" end [score, serialize_value(member)] end ret = dbclient.zadd(dbkey, pairs) update_expiration ret end |