picky 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. data/lib/picky/application.rb +12 -12
  2. data/lib/picky/backends/backend.rb +17 -0
  3. data/lib/picky/{backend → backends}/file/basic.rb +1 -1
  4. data/lib/picky/{backend → backends}/file/json.rb +1 -1
  5. data/lib/picky/{backend → backends}/file/marshal.rb +1 -1
  6. data/lib/picky/{backend → backends}/file/text.rb +1 -1
  7. data/lib/picky/backends/memory.rb +53 -0
  8. data/lib/picky/{backend → backends}/redis/basic.rb +9 -14
  9. data/lib/picky/backends/redis/float_hash.rb +26 -0
  10. data/lib/picky/{backend → backends}/redis/list_hash.rb +7 -11
  11. data/lib/picky/{backend → backends}/redis/string_hash.rb +7 -11
  12. data/lib/picky/backends/redis.rb +87 -0
  13. data/lib/picky/bundle.rb +107 -11
  14. data/lib/picky/category.rb +5 -5
  15. data/lib/picky/index.rb +329 -0
  16. data/lib/picky/index_indexed.rb +31 -0
  17. data/lib/picky/index_indexing.rb +161 -0
  18. data/lib/picky/indexed/bundle.rb +112 -0
  19. data/lib/picky/indexed/wrappers/exact_first.rb +1 -1
  20. data/lib/picky/indexers/parallel.rb +2 -1
  21. data/lib/picky/indexers/serial.rb +2 -1
  22. data/lib/picky/indexes_indexing.rb +1 -1
  23. data/lib/picky/indexing/bundle.rb +188 -0
  24. data/lib/picky/indexing/wrappers/category/location.rb +1 -1
  25. data/lib/picky/interfaces/live_parameters.rb +8 -8
  26. data/lib/picky/loader.rb +24 -38
  27. data/lib/picky/migrations/from_30_to_31.rb +61 -0
  28. data/lib/picky/query/allocation.rb +10 -5
  29. data/lib/picky/query/combinations.rb +70 -0
  30. data/lib/picky/query/indexes.rb +8 -7
  31. data/lib/picky/query/indexes_check.rb +47 -0
  32. data/lib/picky/query/token.rb +16 -29
  33. data/lib/picky/query/tokens.rb +4 -20
  34. data/lib/picky/search.rb +51 -58
  35. data/lib/picky/tokenizer.rb +231 -0
  36. data/lib/picky/tokenizers/location.rb +1 -1
  37. data/lib/tasks/try.rake +4 -12
  38. data/lib/tasks/try.rb +37 -0
  39. data/spec/lib/application_spec.rb +5 -5
  40. data/spec/lib/{backend → backends}/file/basic_spec.rb +2 -2
  41. data/spec/lib/{backend → backends}/file/json_spec.rb +2 -2
  42. data/spec/lib/{backend → backends}/file/marshal_spec.rb +2 -2
  43. data/spec/lib/{backend → backends}/file/text_spec.rb +1 -1
  44. data/spec/lib/backends/memory_spec.rb +77 -0
  45. data/spec/lib/{backend → backends}/redis/basic_spec.rb +19 -21
  46. data/spec/lib/backends/redis/float_hash_spec.rb +38 -0
  47. data/spec/lib/backends/redis/list_hash_spec.rb +27 -0
  48. data/spec/lib/backends/redis/string_hash_spec.rb +38 -0
  49. data/spec/lib/backends/redis_spec.rb +79 -0
  50. data/spec/lib/categories_indexed_spec.rb +3 -3
  51. data/spec/lib/category_indexed_spec.rb +6 -6
  52. data/spec/lib/category_indexing_spec.rb +1 -1
  53. data/spec/lib/category_spec.rb +1 -1
  54. data/spec/lib/frontend_adapters/rack_spec.rb +2 -2
  55. data/spec/lib/{indexes/index_indexed_spec.rb → index_indexed_spec.rb} +1 -1
  56. data/spec/lib/{indexes/index_indexing_spec.rb → index_indexing_spec.rb} +1 -1
  57. data/spec/lib/{indexes/index_spec.rb → index_spec.rb} +1 -1
  58. data/spec/lib/indexed/{bundle/memory_spec.rb → memory_spec.rb} +18 -18
  59. data/spec/lib/indexed/wrappers/exact_first_spec.rb +2 -2
  60. data/spec/lib/indexing/{bundle/memory_partial_generation_speed_spec.rb → bundle_partial_generation_speed_spec.rb} +3 -3
  61. data/spec/lib/indexing/bundle_spec.rb +302 -0
  62. data/spec/lib/query/allocation_spec.rb +21 -11
  63. data/spec/lib/query/combination_spec.rb +2 -2
  64. data/spec/lib/query/{combinations/base_spec.rb → combinations_spec.rb} +1 -1
  65. data/spec/lib/query/indexes_check_spec.rb +25 -0
  66. data/spec/lib/query/indexes_spec.rb +5 -1
  67. data/spec/lib/query/token_spec.rb +18 -20
  68. data/spec/lib/query/tokens_spec.rb +14 -65
  69. data/spec/lib/search_spec.rb +36 -37
  70. data/spec/lib/tasks/try_spec.rb +51 -0
  71. data/spec/lib/{tokenizers/base_spec.rb → tokenizer_spec.rb} +15 -44
  72. metadata +64 -81
  73. data/lib/picky/backend/base.rb +0 -121
  74. data/lib/picky/backend/files.rb +0 -28
  75. data/lib/picky/backend/redis.rb +0 -44
  76. data/lib/picky/indexed/bundle/base.rb +0 -47
  77. data/lib/picky/indexed/bundle/memory.rb +0 -88
  78. data/lib/picky/indexed/bundle/redis.rb +0 -91
  79. data/lib/picky/indexes/index.rb +0 -328
  80. data/lib/picky/indexes/index_indexed.rb +0 -35
  81. data/lib/picky/indexes/index_indexing.rb +0 -165
  82. data/lib/picky/indexes/memory.rb +0 -20
  83. data/lib/picky/indexes/redis.rb +0 -20
  84. data/lib/picky/indexing/bundle/base.rb +0 -242
  85. data/lib/picky/indexing/bundle/memory.rb +0 -26
  86. data/lib/picky/indexing/bundle/redis.rb +0 -26
  87. data/lib/picky/query/combinations/base.rb +0 -74
  88. data/lib/picky/query/combinations/memory.rb +0 -52
  89. data/lib/picky/query/combinations/redis.rb +0 -90
  90. data/lib/picky/query.rb +0 -6
  91. data/lib/picky/tokenizers/base.rb +0 -231
  92. data/lib/picky/tokenizers/index.rb +0 -34
  93. data/lib/picky/tokenizers/query.rb +0 -61
  94. data/spec/lib/backend/files_spec.rb +0 -189
  95. data/spec/lib/backend/redis/list_hash_spec.rb +0 -40
  96. data/spec/lib/backend/redis/string_hash_spec.rb +0 -47
  97. data/spec/lib/backend/redis_spec.rb +0 -170
  98. data/spec/lib/indexed/bundle/redis_spec.rb +0 -41
  99. data/spec/lib/indexes/redis_spec.rb +0 -15
  100. data/spec/lib/indexing/bundle/base_spec.rb +0 -38
  101. data/spec/lib/indexing/bundle/memory_spec.rb +0 -287
  102. data/spec/lib/indexing/bundle/redis_spec.rb +0 -283
  103. data/spec/lib/query/combinations/memory_spec.rb +0 -158
  104. data/spec/lib/query/combinations/redis_spec.rb +0 -172
  105. data/spec/lib/tokenizers/index_spec.rb +0 -69
  106. data/spec/lib/tokenizers/query_spec.rb +0 -121
@@ -0,0 +1,188 @@
1
+ module Picky
2
+
3
+ module Indexing # :nodoc:all
4
+
5
+ # A Bundle is a number of indexes
6
+ # per [index, category] combination.
7
+ #
8
+ # At most, there are three indexes:
9
+ # * *core* index (always used)
10
+ # * *weights* index (always used)
11
+ # * *similarity* index (used with similarity)
12
+ #
13
+ # In Picky, indexing is separated from the index
14
+ # handling itself through a parallel structure.
15
+ #
16
+ # Both use methods provided by this base class, but
17
+ # have very different goals:
18
+ #
19
+ # * *Indexing*::*Bundle* is just concerned with creating index files
20
+ # and providing helper functions to e.g. check the indexes.
21
+ #
22
+ # * *Index*::*Bundle* is concerned with loading these index files into
23
+ # memory and looking up search data as fast as possible.
24
+ #
25
+ # This is the indexing bundle.
26
+ #
27
+ # It does all menial tasks that have nothing to do
28
+ # with the actual index running etc.
29
+ # (Find these in Indexed::Bundle)
30
+ #
31
+ class Bundle < Picky::Bundle
32
+
33
+ attr_reader :backend,
34
+ :prepared
35
+
36
+ attr_accessor :partial_strategy,
37
+ :weights_strategy
38
+
39
+ # When indexing, clear only clears the inverted index.
40
+ #
41
+ delegate :clear, :to => :inverted
42
+
43
+ def initialize name, category, backend, weights_strategy, partial_strategy, similarity_strategy, options = {}
44
+ super name, category, backend, similarity_strategy, options
45
+
46
+ @weights_strategy = weights_strategy
47
+ @partial_strategy = partial_strategy
48
+ @key_format = options[:key_format]
49
+ @prepared = Backends::File::Text.new category.prepared_index_path
50
+
51
+ @inverted = {}
52
+ @weights = {}
53
+ @similarity = {}
54
+ @configuration = {}
55
+ end
56
+
57
+ # Sets up a piece of the index for the given token.
58
+ #
59
+ def initialize_inverted_index_for token
60
+ self.inverted[token] ||= []
61
+ end
62
+
63
+ # Generation
64
+ #
65
+
66
+ # This method
67
+ # * Loads the base index from the "prepared..." file.
68
+ # * Generates derived indexes.
69
+ # * Dumps all the indexes into files.
70
+ #
71
+ def generate_caches_from_source
72
+ load_from_prepared_index_file
73
+ generate_caches_from_memory
74
+ end
75
+ # Generates derived indexes from the index and dumps.
76
+ #
77
+ # Note: assumes that there is something in the index
78
+ #
79
+ def generate_caches_from_memory
80
+ cache_from_memory_generation_message
81
+ generate_derived
82
+ end
83
+ def cache_from_memory_generation_message
84
+ timed_exclaim %Q{"#{identifier}": Caching from intermediate in-memory index.}
85
+ end
86
+
87
+ # Generates the weights and similarity from the main index.
88
+ #
89
+ def generate_derived
90
+ generate_weights
91
+ generate_similarity
92
+ end
93
+
94
+ # Load the data from the db.
95
+ #
96
+ def load_from_prepared_index_file
97
+ load_from_prepared_index_generation_message
98
+ clear
99
+ retrieve
100
+ end
101
+ def load_from_prepared_index_generation_message
102
+ timed_exclaim %Q{"#{identifier}": Loading prepared data into memory.}
103
+ end
104
+ # Retrieves the prepared index data into the index.
105
+ #
106
+ # This is in preparation for generating
107
+ # derived indexes (like weights, similarity)
108
+ # and later dumping the optimized index.
109
+ #
110
+ # TODO Move this out to the category?
111
+ #
112
+ def retrieve
113
+ format = category.key_format || :to_i # Optimization.
114
+ prepared.retrieve do |id, token|
115
+ initialize_inverted_index_for token
116
+ self.inverted[token] << id.send(format)
117
+ end
118
+ end
119
+
120
+ # Generates a new index (writes its index) using the
121
+ # partial caching strategy of this bundle.
122
+ #
123
+ def generate_partial
124
+ generator = Generators::PartialGenerator.new self.inverted
125
+ self.inverted = generator.generate self.partial_strategy
126
+ end
127
+ # Generate a partial index from the given exact inverted index.
128
+ #
129
+ def generate_partial_from exact_inverted_index
130
+ timed_exclaim %Q{"#{identifier}": Generating partial index for index.}
131
+ self.inverted = exact_inverted_index
132
+ self.generate_partial
133
+ self
134
+ end
135
+ # Generates a new weights index (writes its index) using the
136
+ # given weight caching strategy.
137
+ #
138
+ def generate_weights
139
+ generator = Generators::WeightsGenerator.new self.inverted
140
+ self.weights = generator.generate self.weights_strategy
141
+ end
142
+ # Generates a new similarity index (writes its index) using the
143
+ # given similarity caching strategy.
144
+ #
145
+ def generate_similarity
146
+ generator = Generators::SimilarityGenerator.new self.inverted
147
+ self.similarity = generator.generate self.similarity_strategy
148
+ end
149
+
150
+ # Saves the indexes in a dump file.
151
+ #
152
+ def dump
153
+ timed_exclaim %Q{"#{identifier}": Dumping data.}
154
+ dump_inverted
155
+ dump_similarity
156
+ dump_weights
157
+ dump_configuration
158
+ end
159
+ # Dumps the core index.
160
+ #
161
+ def dump_inverted
162
+ # timed_exclaim %Q{"#{identifier}": Dumping inverted index.}
163
+ @backend_inverted.dump self.inverted
164
+ end
165
+ # Dumps the weights index.
166
+ #
167
+ def dump_weights
168
+ # timed_exclaim %Q{"#{identifier}": Dumping index weights.}
169
+ @backend_weights.dump self.weights
170
+ end
171
+ # Dumps the similarity index.
172
+ #
173
+ def dump_similarity
174
+ # timed_exclaim %Q{"#{identifier}": Dumping similarity index.}
175
+ @backend_similarity.dump self.similarity
176
+ end
177
+ # Dumps the similarity index.
178
+ #
179
+ def dump_configuration
180
+ # timed_exclaim %Q{"#{identifier}": Dumping configuration.}
181
+ @backend_configuration.dump self.configuration
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+
188
+ end
@@ -11,7 +11,7 @@ module Picky
11
11
 
12
12
  category.class_eval do
13
13
  def tokenizer
14
- @tokenizer ||= Tokenizers::Index.new
14
+ @tokenizer ||= Tokenizer.new
15
15
  end
16
16
  define_method :source do
17
17
  new_source
@@ -144,29 +144,29 @@ module Picky
144
144
  # TODO Move to Interface object.
145
145
  #
146
146
  def querying_removes_characters
147
- regexp = Tokenizers::Query.default.instance_variable_get :@removes_characters_regexp
147
+ regexp = Tokenizer.query_default.instance_variable_get :@removes_characters_regexp
148
148
  regexp && regexp.source
149
149
  end
150
150
  def querying_removes_characters= new_value
151
- Tokenizers::Query.default.instance_variable_set(:@removes_characters_regexp, %r{#{new_value}})
151
+ Tokenizer.query_default.instance_variable_set(:@removes_characters_regexp, %r{#{new_value}})
152
152
  end
153
153
  def querying_stopwords
154
- regexp = Tokenizers::Query.default.instance_variable_get :@remove_stopwords_regexp
154
+ regexp = Tokenizer.query_default.instance_variable_get :@remove_stopwords_regexp
155
155
  regexp && regexp.source
156
156
  end
157
157
  def querying_stopwords= new_value
158
- Tokenizers::Query.default.instance_variable_set(:@remove_stopwords_regexp, %r{#{new_value}})
158
+ Tokenizer.query_default.instance_variable_set(:@remove_stopwords_regexp, %r{#{new_value}})
159
159
  end
160
160
  def querying_splits_text_on
161
- splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on
161
+ splits = Tokenizer.query_default.instance_variable_get :@splits_text_on
162
162
  splits && splits.respond_to?(:source) ? splits.source : splits
163
163
  end
164
164
  def querying_splits_text_on= new_value
165
- splits = Tokenizers::Query.default.instance_variable_get :@splits_text_on
165
+ splits = Tokenizer.query_default.instance_variable_get :@splits_text_on
166
166
  if splits.respond_to?(:source)
167
- Tokenizers::Query.default.instance_variable_set(:@splits_text_on, %r{#{new_value}})
167
+ Tokenizer.query_default.instance_variable_set(:@splits_text_on, %r{#{new_value}})
168
168
  else
169
- Tokenizers::Query.default.instance_variable_set(:@splits_text_on, new_value)
169
+ Tokenizer.query_default.instance_variable_set(:@splits_text_on, new_value)
170
170
  end
171
171
  end
172
172
 
data/lib/picky/loader.rb CHANGED
@@ -110,34 +110,28 @@ module Picky
110
110
 
111
111
  # Index store handling.
112
112
  #
113
- load_relative 'backend/base'
113
+ load_relative 'backends/backend'
114
114
 
115
- load_relative 'backend/redis'
116
- load_relative 'backend/redis/basic'
117
- load_relative 'backend/redis/list_hash'
118
- load_relative 'backend/redis/string_hash'
115
+ load_relative 'backends/redis'
116
+ load_relative 'backends/redis/basic'
117
+ load_relative 'backends/redis/list_hash'
118
+ load_relative 'backends/redis/string_hash'
119
+ load_relative 'backends/redis/float_hash'
119
120
 
120
- load_relative 'backend/file/basic'
121
- load_relative 'backend/file/text'
122
- load_relative 'backend/file/marshal'
123
- load_relative 'backend/file/json'
124
-
125
- load_relative 'backend/files'
121
+ load_relative 'backends/file/basic'
122
+ load_relative 'backends/file/text'
123
+ load_relative 'backends/file/marshal'
124
+ load_relative 'backends/file/json'
125
+ load_relative 'backends/memory'
126
126
 
127
127
  # Indexing and Indexed things.
128
128
  #
129
129
  load_relative 'bundle'
130
130
 
131
- load_relative 'indexing/bundle/base'
132
- load_relative 'indexing/bundle/memory'
133
- load_relative 'indexing/bundle/redis'
134
-
131
+ load_relative 'indexing/bundle'
135
132
  load_relative 'indexing/wrappers/category/location'
136
133
 
137
- load_relative 'indexed/bundle/base'
138
- load_relative 'indexed/bundle/memory'
139
- load_relative 'indexed/bundle/redis'
140
-
134
+ load_relative 'indexed/bundle'
141
135
  load_relative 'indexed/wrappers/exact_first'
142
136
 
143
137
  # Bundle Wrapper
@@ -153,18 +147,14 @@ module Picky
153
147
  load_relative 'query/token'
154
148
  load_relative 'query/tokens'
155
149
 
156
- # Tokenizers types.
150
+ # Tokenizer.
157
151
  #
158
- load_relative 'tokenizers/base'
159
- load_relative 'tokenizers/index'
160
- load_relative 'tokenizers/query'
152
+ load_relative 'tokenizer'
161
153
 
162
154
  # Query combinations, qualifiers, weigher.
163
155
  #
164
156
  load_relative 'query/combination'
165
- load_relative 'query/combinations/base'
166
- load_relative 'query/combinations/memory'
167
- load_relative 'query/combinations/redis'
157
+ load_relative 'query/combinations'
168
158
 
169
159
  load_relative 'query/allocation'
170
160
  load_relative 'query/allocations'
@@ -174,10 +164,7 @@ module Picky
174
164
  load_relative 'query/weights'
175
165
 
176
166
  load_relative 'query/indexes'
177
-
178
- # Configuration.
179
- #
180
- # load_internals 'configuration/index'
167
+ load_relative 'query/indexes_check'
181
168
 
182
169
  # Adapters.
183
170
  #
@@ -227,11 +214,9 @@ module Picky
227
214
  load_relative 'indexes_indexed'
228
215
  load_relative 'indexes_indexing'
229
216
 
230
- load_relative 'indexes/index'
231
- load_relative 'indexes/index_indexed'
232
- load_relative 'indexes/index_indexing'
233
- load_relative 'indexes/memory'
234
- load_relative 'indexes/redis'
217
+ load_relative 'index'
218
+ load_relative 'index_indexed'
219
+ load_relative 'index_indexing'
235
220
 
236
221
  # Results.
237
222
  #
@@ -240,9 +225,6 @@ module Picky
240
225
  # Search.
241
226
  #
242
227
  load_relative 'search'
243
- load_relative 'query'
244
- #
245
- # load_relative 'query/solr'
246
228
 
247
229
  # Sources.
248
230
  #
@@ -267,6 +249,10 @@ module Picky
267
249
  # Load tools. Load in specific case?
268
250
  #
269
251
  load_relative 'cores'
252
+
253
+ # Load migration notices.
254
+ #
255
+ load_relative 'migrations/from_30_to_31'
270
256
  end
271
257
 
272
258
  # Loads the framework.
@@ -0,0 +1,61 @@
1
+ module Picky
2
+
3
+ class Indexes
4
+
5
+ class Memory
6
+
7
+ def initialize(*)
8
+ raise <<-MESSAGE
9
+
10
+ The Picky::Indexes::Memory is not available anymore and has been replaced by Picky::Index.
11
+
12
+ So instead of
13
+
14
+ index = Picky::Indexes::Memory.new :name do
15
+ # your config
16
+ end
17
+
18
+ use
19
+
20
+ index = Picky::Index.new :name do
21
+ # your config
22
+ end
23
+
24
+ Thanks and sorry for the inconvenience!
25
+
26
+ MESSAGE
27
+ end
28
+
29
+ end
30
+
31
+ class Redis
32
+
33
+ def initialize(*)
34
+ raise <<-RAISE
35
+
36
+ The Picky::Indexes::Redis is not available anymore and has been replaced by Picky::Index.
37
+ (with the addition of a "backend" option)
38
+
39
+ So instead of
40
+
41
+ index = Picky::Indexes::Redis.new :name do
42
+ # your config
43
+ end
44
+
45
+ use
46
+
47
+ index = Picky::Index.new :name do
48
+ backend Picky::Backends::Redis.new
49
+ # your config
50
+ end
51
+
52
+ Thanks and sorry for the inconvenience!
53
+
54
+ RAISE
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -7,13 +7,18 @@ module Picky
7
7
  #
8
8
  class Allocation # :nodoc:all
9
9
 
10
- attr_reader :count, :ids, :score, :combinations, :result_identifier
10
+ attr_reader :count,
11
+ :ids,
12
+ :score,
13
+ :combinations,
14
+ :result_identifier
11
15
 
12
16
  #
13
17
  #
14
- def initialize combinations, result_identifier
18
+ def initialize index, combinations
15
19
  @combinations = combinations
16
- @result_identifier = result_identifier
20
+ @result_identifier = index.result_identifier # TODO Make cleverer.
21
+ @backend = index.backend # TODO Make cleverer.
17
22
  end
18
23
 
19
24
  def hash
@@ -30,10 +35,10 @@ module Picky
30
35
  @score ||= @combinations.calculate_score(weights)
31
36
  end
32
37
 
33
- # Asks the combinations for the (intersected) ids.
38
+ # Asks the backend for the (intersected) ids.
34
39
  #
35
40
  def calculate_ids amount, offset
36
- @combinations.ids amount, offset # Calculate as many ids as are necessary.
41
+ @backend.ids combinations, amount, offset
37
42
  end
38
43
 
39
44
  # This starts the searching process.
@@ -0,0 +1,70 @@
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ # Combinations are a number of Combination-s.
6
+ #
7
+ # They are the core of an allocation.
8
+ # An allocation consists of a number of combinations.
9
+ #
10
+ # Base Combinations contain methods for calculating score and ids.
11
+ #
12
+ class Combinations # :nodoc:all
13
+
14
+ attr_reader :combinations
15
+
16
+ delegate :empty?, :inject, :to => :@combinations
17
+
18
+ def initialize combinations = []
19
+ @combinations = combinations
20
+ end
21
+
22
+ def hash
23
+ @combinations.hash
24
+ end
25
+
26
+ # Uses user specific weights to calculate a score for the combinations.
27
+ #
28
+ def calculate_score weights
29
+ total_score + weighted_score(weights)
30
+ end
31
+ def total_score
32
+ @combinations.sum &:weight
33
+ end
34
+ def weighted_score weights
35
+ weights.score_for @combinations
36
+ end
37
+
38
+ # Filters the tokens and identifiers such that only identifiers
39
+ # that are passed in, remain, including their tokens.
40
+ #
41
+ # Note: This method is not totally independent of the calculate_ids one.
42
+ # Since identifiers are only nullified, we need to not include the
43
+ # ids that have an associated identifier that is nil.
44
+ #
45
+ def keep identifiers = []
46
+ @combinations.reject! { |combination| !combination.in?(identifiers) }
47
+ end
48
+
49
+ # Filters the tokens and identifiers such that identifiers
50
+ # that are passed in, are removed, including their tokens.
51
+ #
52
+ # Note: This method is not totally independent of the calculate_ids one.
53
+ # Since identifiers are only nullified, we need to not include the
54
+ # ids that have an associated identifier that is nil.
55
+ #
56
+ def remove identifiers = []
57
+ @combinations.reject! { |combination| combination.in?(identifiers) }
58
+ end
59
+
60
+ #
61
+ #
62
+ def to_result
63
+ @combinations.map &:to_result
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -20,10 +20,11 @@ module Picky
20
20
  # Its job is to generate all possible combinations.
21
21
  # Note: We cannot mix memory and redis indexes just yet.
22
22
  #
23
- def initialize *indexes, combinations_type
24
- @indexes = indexes
25
- @combinations_type = combinations_type
26
- @mapper = Query::QualifierCategoryMapper.new
23
+ def initialize *indexes
24
+ IndexesCheck.check_backend_types indexes
25
+
26
+ @indexes = indexes
27
+ @mapper = Query::QualifierCategoryMapper.new
27
28
  map_categories
28
29
  end
29
30
  def map_categories
@@ -81,12 +82,12 @@ module Picky
81
82
 
82
83
  # Generate all possible combinations.
83
84
  #
84
- expanded_combinations = expand_combinations_from possible_combinations
85
+ all_possible_combinations = expand_combinations_from possible_combinations
85
86
 
86
87
  # Add the wrapped possible allocations to the ones we already have.
87
88
  #
88
- expanded_combinations.map! do |expanded_combination|
89
- Allocation.new @combinations_type.new(expanded_combination), index.result_identifier # TODO Do not extract result_identifier.
89
+ all_possible_combinations.map! do |expanded_combinations|
90
+ Allocation.new index, Query::Combinations.new(expanded_combinations)
90
91
  end
91
92
  end
92
93
 
@@ -0,0 +1,47 @@
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ # TODO Remove.
6
+ #
7
+ class IndexesCheck
8
+
9
+ class << self
10
+
11
+ # Returns the right combinations strategy for
12
+ # a number of query indexes.
13
+ #
14
+ # Currently it isn't possible using Memory and Redis etc.
15
+ # indexes in the same query index group.
16
+ #
17
+ # Picky will raise a Query::Indexes::DifferentTypesError.
18
+ #
19
+ def check_backend_types index_definitions_ary # :nodoc:
20
+ backend_types = index_definitions_ary.map(&:backend).map(&:class)
21
+ backend_types.uniq!
22
+ raise_different backend_types if backend_types.size > 1
23
+ backend_types
24
+ end
25
+ def raise_different backend_types # :nodoc:
26
+ raise DifferentTypesError.new(backend_types)
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ # Currently it isn't possible using Memory and Redis etc.
34
+ # indexes in the same query index group.
35
+ #
36
+ class DifferentTypesError < StandardError # :nodoc:all
37
+ def initialize types
38
+ @types = types
39
+ end
40
+ def to_s
41
+ "Currently it isn't possible to mix Indexes with backends #{@types.join(" and ")} in the same Search instance."
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -19,8 +19,9 @@ module Picky
19
19
  #
20
20
  # Note: Use this if you do not want a normalized token.
21
21
  #
22
- def initialize text
23
- @text = text
22
+ def initialize text, original = nil
23
+ @text = text
24
+ @original = original
24
25
  end
25
26
 
26
27
  # Returns a qualified and normalized token.
@@ -28,20 +29,24 @@ module Picky
28
29
  # Note: Use this in the search engine if you need a qualified
29
30
  # and normalized token. I.e. one prepared for a search.
30
31
  #
31
- def self.processed text, downcase = true
32
- new(text).process downcase
32
+ def self.processed text, original = nil
33
+ new(text, original).process
33
34
  end
34
- def process downcased = true
35
- qualify
36
- extract_original
37
- downcase if downcased
38
- partialize
39
- similarize
40
- remove_illegals
35
+ def process # TODO Move this into the processed method and let the token have more params?
36
+ qualify # TODO Should this operate on the original?
37
+ partialize # TODO Should this operate on the original?
38
+ similarize # TODO Should this operate on the original?
39
+ remove_illegals # TODO Remove?
41
40
  symbolize
42
41
  self
43
42
  end
44
43
 
44
+ #
45
+ #
46
+ def symbolize
47
+ @text = @text.to_sym
48
+ end
49
+
45
50
  # Translates this token's qualifiers into actual categories.
46
51
  #
47
52
  # Note: If this is not done, there is no mapping.
@@ -52,18 +57,6 @@ module Picky
52
57
  end.compact
53
58
  end
54
59
 
55
- # Dups the original text.
56
- #
57
- def extract_original
58
- @original = @text.dup
59
- end
60
-
61
- # Downcases the text.
62
- #
63
- def downcase
64
- @text.downcase!
65
- end
66
-
67
60
  # Partial is a conditional setter.
68
61
  #
69
62
  # It is only settable if it hasn't been set yet.
@@ -108,12 +101,6 @@ module Picky
108
101
  @text.gsub! @@illegals, '' unless @text.blank?
109
102
  end
110
103
 
111
- #
112
- #
113
- def symbolize
114
- @text = @text.to_sym
115
- end
116
-
117
104
  # Returns an array of possible combinations.
118
105
  #
119
106
  def possible_combinations_in index