Module: Predictor::Base
- Defined in:
- lib/predictor/base.rb
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
- #add_to_matrix(matrix, set, *items) ⇒ Object
- #add_to_matrix!(matrix, set, *items) ⇒ Object
- #all_items ⇒ Object
- #clean! ⇒ Object
- #delete_from_matrix!(matrix, item) ⇒ Object
- #delete_item!(item) ⇒ Object
- #ensure_similarity_limit_is_obeyed! ⇒ Object
- #input_matrices ⇒ Object
- #method_missing(method, *args) ⇒ Object
- #predictions_for(set = nil, item_set: nil, matrix_label: nil, with_scores: false, offset: 0, limit: -1,, exclusion_set: []) ⇒ Object
- #process! ⇒ Object
- #process_item!(item) ⇒ Object
- #process_items!(*items) ⇒ Object
- #redis_key(*append) ⇒ Object
- #redis_prefix ⇒ Object
- #related_items(item) ⇒ Object
- #respond_to?(method) ⇒ Boolean
- #sets_for(item) ⇒ Object
- #similarities_for(item, with_scores: false, offset: 0, limit: -1,, exclusion_set: []) ⇒ Object
- #similarity_limit ⇒ Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
54 55 56 57 58 59 60 |
# File 'lib/predictor/base.rb', line 54 def method_missing(method, *args) if input_matrices.has_key?(method) input_matrices[method] else raise NoMethodError.new(method.to_s) end end |
Class Method Details
.included(base) ⇒ Object
2 3 4 |
# File 'lib/predictor/base.rb', line 2 def self.included(base) base.extend(ClassMethods) end |
Instance Method Details
#add_to_matrix(matrix, set, *items) ⇒ Object
70 71 72 73 |
# File 'lib/predictor/base.rb', line 70 def add_to_matrix(matrix, set, *items) items = items.flatten if items.count == 1 && items[0].is_a?(Array) # Old syntax input_matrices[matrix].add_to_set(set, *items) end |
#add_to_matrix!(matrix, set, *items) ⇒ Object
75 76 77 78 79 |
# File 'lib/predictor/base.rb', line 75 def add_to_matrix!(matrix, set, *items) items = items.flatten if items.count == 1 && items[0].is_a?(Array) # Old syntax add_to_matrix(matrix, set, *items) process_items!(*items) end |
#all_items ⇒ Object
66 67 68 |
# File 'lib/predictor/base.rb', line 66 def all_items Predictor.redis.smembers(redis_key(:all_items)) end |
#clean! ⇒ Object
171 172 173 174 175 176 |
# File 'lib/predictor/base.rb', line 171 def clean! keys = Predictor.redis.keys("#{self.redis_prefix}:*") unless keys.empty? Predictor.redis.del(keys) end end |
#delete_from_matrix!(matrix, item) ⇒ Object
145 146 147 148 149 150 151 |
# File 'lib/predictor/base.rb', line 145 def delete_from_matrix!(matrix, item) # Deleting from a specific matrix, so get related_items, delete, then update the similarity of those related_items items = (item) input_matrices[matrix].delete_item(item) items.each { || cache_similarity(item, ) } return self end |
#delete_item!(item) ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/predictor/base.rb', line 153 def delete_item!(item) Predictor.redis.srem(redis_key(:all_items), item) Predictor.redis.watch(redis_key(:similarities, item)) do items = (item) Predictor.redis.multi do |multi| items.each do || multi.zrem(redis_key(:similarities, ), item) end multi.del redis_key(:similarities, item) end end input_matrices.each do |k,m| m.delete_item(item) end return self end |
#ensure_similarity_limit_is_obeyed! ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/predictor/base.rb', line 178 def ensure_similarity_limit_is_obeyed! if similarity_limit items = all_items Predictor.redis.multi do |multi| items.each do |item| key = redis_key(:similarities, item) multi.zremrangebyrank(key, 0, -(similarity_limit + 1)) multi.zunionstore key, [key] # Rewrite zset to take advantage of ziplist implementation. end end end end |
#input_matrices ⇒ Object
35 36 37 38 39 40 |
# File 'lib/predictor/base.rb', line 35 def input_matrices @input_matrices ||= Hash[self.class.input_matrices.map{ |key, opts| opts.merge!(:key => key, :redis_prefix => redis_prefix) [ key, Predictor::InputMatrix.new(opts) ] }] end |
#predictions_for(set = nil, item_set: nil, matrix_label: nil, with_scores: false, offset: 0, limit: -1,, exclusion_set: []) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/predictor/base.rb', line 91 def predictions_for(set=nil, item_set: nil, matrix_label: nil, with_scores: false, offset: 0, limit: -1, exclusion_set: []) fail "item_set or matrix_label and set is required" unless item_set || (matrix_label && set) if matrix_label matrix = input_matrices[matrix_label] item_set = Predictor.redis.smembers(matrix.redis_key(:items, set)) end item_keys = item_set.map { |item| redis_key(:similarities, item) } return [] if item_keys.empty? predictions = nil Predictor.redis.multi do |multi| multi.zunionstore 'temp', item_keys multi.zrem 'temp', item_set multi.zrem 'temp', exclusion_set if exclusion_set.length > 0 predictions = multi.zrevrange 'temp', offset, limit == -1 ? limit : offset + (limit - 1), with_scores: with_scores multi.del 'temp' end predictions.value end |
#process! ⇒ Object
140 141 142 143 |
# File 'lib/predictor/base.rb', line 140 def process! process_items!(*all_items) return self end |
#process_item!(item) ⇒ Object
128 129 130 |
# File 'lib/predictor/base.rb', line 128 def process_item!(item) process_items!(item) # Old method end |
#process_items!(*items) ⇒ Object
132 133 134 135 136 137 138 |
# File 'lib/predictor/base.rb', line 132 def process_items!(*items) items = items.flatten if items.count == 1 && items[0].is_a?(Array) # Old syntax items.each do |item| (item).each{ || cache_similarity(item, ) } end return self end |
#redis_key(*append) ⇒ Object
50 51 52 |
# File 'lib/predictor/base.rb', line 50 def redis_key(*append) ([redis_prefix] + append).flatten.compact.join(":") end |
#redis_prefix ⇒ Object
42 43 44 |
# File 'lib/predictor/base.rb', line 42 def redis_prefix "predictor" end |
#related_items(item) ⇒ Object
81 82 83 84 85 86 87 88 89 |
# File 'lib/predictor/base.rb', line 81 def (item) keys = [] input_matrices.each do |key, matrix| sets = Predictor.redis.smembers(matrix.redis_key(:sets, item)) keys.concat(sets.map { |set| matrix.redis_key(:items, set) }) end keys.empty? ? [] : (Predictor.redis.sunion(keys) - [item.to_s]) end |
#respond_to?(method) ⇒ Boolean
62 63 64 |
# File 'lib/predictor/base.rb', line 62 def respond_to?(method) input_matrices.has_key?(method) ? true : super end |
#sets_for(item) ⇒ Object
123 124 125 126 |
# File 'lib/predictor/base.rb', line 123 def sets_for(item) keys = input_matrices.map{ |k,m| m.redis_key(:sets, item) } Predictor.redis.sunion keys end |
#similarities_for(item, with_scores: false, offset: 0, limit: -1,, exclusion_set: []) ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/predictor/base.rb', line 112 def similarities_for(item, with_scores: false, offset: 0, limit: -1, exclusion_set: []) neighbors = nil Predictor.redis.multi do |multi| multi.zunionstore 'temp', [1, redis_key(:similarities, item)] multi.zrem 'temp', exclusion_set if exclusion_set.length > 0 neighbors = multi.zrevrange('temp', offset, limit == -1 ? limit : offset + (limit - 1), with_scores: with_scores) multi.del 'temp' end return neighbors.value end |
#similarity_limit ⇒ Object
46 47 48 |
# File 'lib/predictor/base.rb', line 46 def similarity_limit self.class.similarity_limit end |