module Lunar class Search attr :sets, :prefix, :search_identifier, :fuzzy_sets, :key_value_sets def initialize(prefix, keywords) if keywords.is_a?(Hash) if fuzzy_hash = keywords.delete(:fuzzy) @fuzzy_sets = fuzzy_hash.inject([]) { |a, (field, query)| a | FuzzySets.new(prefix, query, field) } @search_identifier = fuzzy_hash.hash else @key_value_sets = keywords.map { |field, val| Sets.new(prefix, val, field) }.flatten @search_identifier = keywords.hash end else @sets = Sets.new(prefix, keywords) @search_identifier = keywords.hash end @prefix = prefix # Default finder, uses Ohm style finding @finder = lambda { |id| prefix[id] } end def results(&block) block ||= @finder if sets if sets.empty? return [] else if not Lunar.redis.exists(dist_key) Lunar.redis.zunion dist_key, sets.size, *sets Lunar.redis.expire dist_key, Lunar.ttl end SortedResultSet.new(dist_key, &block) end elsif key_value_sets if key_value_sets.empty? return [] else Lunar.redis.zinter dist_key, key_value_sets.size, *key_value_sets SortedResultSet.new(dist_key, &block) end elsif fuzzy_sets if fuzzy_sets.empty? return [] else if not Lunar.redis.exists(dist_key) Lunar.redis.sunionstore dist_key, *fuzzy_sets Lunar.redis.expire dist_key, Lunar.ttl end UnsortedResultSet.new(dist_key, &block) end end end protected def dist_key Lunar.nest[:Results][search_identifier] end end end