class Query
Public Class Methods
new(criteria)
click to toggle source
# File lib/redisant/query.rb, line 3 def initialize criteria @criteria = criteria end
Public Instance Methods
run()
click to toggle source
# File lib/redisant/query.rb, line 7 def run raise "Count and random cannot be combined" if @criteria.count? && @criteria.random? collect_keys if @criteria.count? return count elsif @criteria.random? random else fetch end if @criteria.criteria[:exists] any? elsif @criteria.ids? flatten_single_items @ids else load_objects flatten_single_items @objects end ensure delete_tmp end
Private Instance Methods
any?()
click to toggle source
# File lib/redisant/query.rb, line 33 def any? @ids and @ids.any? end
collect_keys()
click to toggle source
# File lib/redisant/query.rb, line 37 def collect_keys @sub_keys = [] # start from a has_many relation? @sub_keys << @criteria.ids_key if @criteria.get_relation || @criteria.get_conditions.empty? # where conditions name = @criteria.object_class.name.downcase @criteria.get_conditions.each_pair do |k,v| @sub_keys << "#{name}:search:#{k}:#{v}" end @final_key = @sub_keys.first if @sub_keys.size == 1 end
count()
click to toggle source
# File lib/redisant/query.rb, line 51 def count if @sub_keys.size > 1 count_intersection else count_ids end end
count_ids()
click to toggle source
# File lib/redisant/query.rb, line 152 def count_ids @result = $redis.scard @final_key end
count_intersection()
click to toggle source
# File lib/redisant/query.rb, line 116 def count_intersection lua = "return #redis.call('SINTER', unpack(KEYS));" $redis.eval lua, @sub_keys end
count_set()
click to toggle source
# File lib/redisant/query.rb, line 121 def count_set $redis.scard @final_key end
delete_tmp()
click to toggle source
# File lib/redisant/query.rb, line 101 def delete_tmp $redis.del @final_key if @del @del = nil end
fetch()
click to toggle source
# File lib/redisant/query.rb, line 67 def fetch if @sub_keys.size > 1 if @criteria.sort? || @criteria.limit? || @criteria.single? store_intersection @ids = sort_and_limit else @ids = fetch_intersection end else @final_key = @sub_keys.first @ids = sort_and_limit end end
fetch_intersection()
click to toggle source
# File lib/redisant/query.rb, line 89 def fetch_intersection got = $redis.sinter @sub_keys got.map { |id| id.to_i } if got end
flatten_single_items(a)
click to toggle source
# File lib/redisant/query.rb, line 81 def flatten_single_items a if @criteria.single? a.first else a end end
load_objects()
click to toggle source
# File lib/redisant/query.rb, line 164 def load_objects @objects = @ids.map { |id| @criteria.object_class.load id } end
random()
click to toggle source
# File lib/redisant/query.rb, line 59 def random if @sub_keys.size > 1 @ids = [random_intersection] else @ids = [random_ids] end end
random_ids()
click to toggle source
# File lib/redisant/query.rb, line 156 def random_ids $redis.srandmember(@final_key).to_i end
random_intersection()
click to toggle source
# File lib/redisant/query.rb, line 106 def random_intersection # random numbers in redis lua scripts must be seeded with an outside integer lua = " math.randomseed(tonumber(ARGV[1])) local ids=redis.call('SINTER', unpack(KEYS)) return ids[ math.random(#ids) ] " $redis.eval(lua, @sub_keys, [rand(2**32)]).to_i end
random_set()
click to toggle source
# File lib/redisant/query.rb, line 160 def random_set $redis.srandmember(@final_key).to_i end
sort_and_limit()
click to toggle source
# File lib/redisant/query.rb, line 125 def sort_and_limit criteria = @criteria.criteria sort = criteria[:sort] # use dup because string might be frozen, and we might need to modify it later order = criteria[:order].to_s.dup || 'asc' if criteria[:limit] limit = [criteria[:offset] || 0, criteria[:limit]] end if sort index = @criteria.object_class.find_index(sort) type = index.type by = "#{@criteria.object_class.name.downcase}:*:attributes->#{sort}" by << ":float" if type == 'float' if type == 'string' order << ' alpha' end else by = 'nosort' unless criteria[:limit]==1 end ids = $redis.sort @final_key, limit: limit, by: by, order: order ids.map! { |t| t.to_i } if ids end
store_intersection()
click to toggle source
# File lib/redisant/query.rb, line 94 def store_intersection # combine search sets to temporary set that we can sort later @final_key = "tmp:#{rand(36**16).to_s(36)}" $redis.sinterstore @final_key, @sub_keys @del = true end