picky 2.7.0 → 3.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. data/lib/picky/adapters/rack/base.rb +20 -16
  2. data/lib/picky/adapters/rack/live_parameters.rb +28 -24
  3. data/lib/picky/adapters/rack/search.rb +67 -0
  4. data/lib/picky/adapters/rack.rb +27 -23
  5. data/lib/picky/application.rb +246 -236
  6. data/lib/picky/backend/base.rb +115 -119
  7. data/lib/picky/backend/file/basic.rb +102 -98
  8. data/lib/picky/backend/file/json.rb +27 -23
  9. data/lib/picky/backend/file/marshal.rb +32 -28
  10. data/lib/picky/backend/file/text.rb +45 -41
  11. data/lib/picky/backend/files.rb +19 -15
  12. data/lib/picky/backend/redis/basic.rb +76 -72
  13. data/lib/picky/backend/redis/list_hash.rb +40 -36
  14. data/lib/picky/backend/redis/string_hash.rb +30 -26
  15. data/lib/picky/backend/redis.rb +32 -28
  16. data/lib/picky/bundle.rb +82 -57
  17. data/lib/{bundling.rb → picky/bundling.rb} +0 -0
  18. data/lib/picky/calculations/location.rb +51 -47
  19. data/lib/picky/categories.rb +60 -56
  20. data/lib/picky/categories_indexed.rb +73 -82
  21. data/lib/picky/categories_indexing.rb +12 -8
  22. data/lib/picky/category.rb +109 -120
  23. data/lib/picky/category_indexed.rb +39 -41
  24. data/lib/picky/category_indexing.rb +123 -125
  25. data/lib/picky/character_substituters/west_european.rb +32 -26
  26. data/lib/{constants.rb → picky/constants.rb} +0 -0
  27. data/lib/picky/cores.rb +96 -92
  28. data/lib/{deployment.rb → picky/deployment.rb} +0 -0
  29. data/lib/picky/frontend_adapters/rack.rb +133 -118
  30. data/lib/picky/generators/aliases.rb +5 -3
  31. data/lib/picky/generators/base.rb +11 -7
  32. data/lib/picky/generators/partial/default.rb +7 -3
  33. data/lib/picky/generators/partial/none.rb +24 -20
  34. data/lib/picky/generators/partial/strategy.rb +20 -16
  35. data/lib/picky/generators/partial/substring.rb +94 -90
  36. data/lib/picky/generators/partial_generator.rb +11 -7
  37. data/lib/picky/generators/similarity/default.rb +9 -5
  38. data/lib/picky/generators/similarity/double_metaphone.rb +20 -16
  39. data/lib/picky/generators/similarity/metaphone.rb +20 -16
  40. data/lib/picky/generators/similarity/none.rb +23 -19
  41. data/lib/picky/generators/similarity/phonetic.rb +49 -45
  42. data/lib/picky/generators/similarity/soundex.rb +20 -16
  43. data/lib/picky/generators/similarity/strategy.rb +10 -6
  44. data/lib/picky/generators/similarity_generator.rb +11 -7
  45. data/lib/picky/generators/strategy.rb +14 -10
  46. data/lib/picky/generators/weights/default.rb +9 -5
  47. data/lib/picky/generators/weights/logarithmic.rb +30 -26
  48. data/lib/picky/generators/weights/strategy.rb +10 -6
  49. data/lib/picky/generators/weights_generator.rb +11 -7
  50. data/lib/picky/helpers/measuring.rb +20 -16
  51. data/lib/picky/indexed/bundle/base.rb +39 -37
  52. data/lib/picky/indexed/bundle/memory.rb +68 -64
  53. data/lib/picky/indexed/bundle/redis.rb +73 -69
  54. data/lib/picky/indexed/wrappers/bundle/calculation.rb +26 -22
  55. data/lib/picky/indexed/wrappers/bundle/location.rb +30 -26
  56. data/lib/picky/indexed/wrappers/bundle/wrapper.rb +36 -32
  57. data/lib/picky/indexed/wrappers/category/location.rb +17 -13
  58. data/lib/picky/indexed/wrappers/exact_first.rb +46 -42
  59. data/lib/picky/indexers/base.rb +26 -22
  60. data/lib/picky/indexers/parallel.rb +62 -58
  61. data/lib/picky/indexers/serial.rb +41 -37
  62. data/lib/picky/indexes/index.rb +400 -0
  63. data/lib/picky/indexes/index_indexed.rb +24 -0
  64. data/lib/picky/indexes/index_indexing.rb +138 -0
  65. data/lib/picky/indexes/memory.rb +20 -0
  66. data/lib/picky/indexes/redis.rb +20 -0
  67. data/lib/picky/indexes.rb +68 -61
  68. data/lib/picky/indexes_indexed.rb +16 -12
  69. data/lib/picky/indexes_indexing.rb +41 -37
  70. data/lib/picky/indexing/bundle/base.rb +216 -205
  71. data/lib/picky/indexing/bundle/memory.rb +16 -11
  72. data/lib/picky/indexing/bundle/redis.rb +14 -12
  73. data/lib/picky/indexing/wrappers/category/location.rb +17 -13
  74. data/lib/picky/interfaces/live_parameters.rb +159 -154
  75. data/lib/picky/loader.rb +267 -304
  76. data/lib/picky/loggers/search.rb +20 -13
  77. data/lib/picky/no_source_specified_exception.rb +7 -3
  78. data/lib/picky/performant.rb +6 -2
  79. data/lib/picky/query/allocation.rb +71 -67
  80. data/lib/picky/query/allocations.rb +99 -94
  81. data/lib/picky/query/combination.rb +70 -66
  82. data/lib/picky/query/combinations/base.rb +56 -52
  83. data/lib/picky/query/combinations/memory.rb +36 -32
  84. data/lib/picky/query/combinations/redis.rb +66 -62
  85. data/lib/picky/query/indexes.rb +175 -160
  86. data/lib/picky/query/qualifier_category_mapper.rb +43 -0
  87. data/lib/picky/query/token.rb +165 -172
  88. data/lib/picky/query/tokens.rb +86 -82
  89. data/lib/picky/query/weights.rb +44 -48
  90. data/lib/picky/query.rb +5 -1
  91. data/lib/picky/rack/harakiri.rb +51 -47
  92. data/lib/picky/results.rb +81 -77
  93. data/lib/picky/search.rb +169 -158
  94. data/lib/picky/sinatra.rb +34 -0
  95. data/lib/picky/sources/base.rb +73 -70
  96. data/lib/picky/sources/couch.rb +61 -57
  97. data/lib/picky/sources/csv.rb +68 -64
  98. data/lib/picky/sources/db.rb +139 -135
  99. data/lib/picky/sources/delicious.rb +52 -48
  100. data/lib/picky/sources/mongo.rb +68 -63
  101. data/lib/picky/sources/wrappers/base.rb +20 -16
  102. data/lib/picky/sources/wrappers/location.rb +37 -33
  103. data/lib/picky/statistics.rb +46 -43
  104. data/lib/picky/tasks.rb +3 -0
  105. data/lib/picky/tokenizers/base.rb +192 -187
  106. data/lib/picky/tokenizers/index.rb +25 -21
  107. data/lib/picky/tokenizers/location.rb +33 -29
  108. data/lib/picky/tokenizers/query.rb +49 -43
  109. data/lib/picky.rb +21 -13
  110. data/lib/tasks/application.rake +1 -1
  111. data/lib/tasks/index.rake +3 -3
  112. data/lib/tasks/routes.rake +1 -1
  113. data/lib/tasks/server.rake +1 -1
  114. data/spec/lib/adapters/rack/base_spec.rb +1 -1
  115. data/spec/lib/adapters/rack/live_parameters_spec.rb +1 -1
  116. data/spec/lib/adapters/rack/query_spec.rb +1 -1
  117. data/spec/lib/application_spec.rb +39 -32
  118. data/spec/lib/backend/file/basic_spec.rb +2 -2
  119. data/spec/lib/backend/file/json_spec.rb +2 -2
  120. data/spec/lib/backend/file/marshal_spec.rb +2 -2
  121. data/spec/lib/backend/file/text_spec.rb +1 -1
  122. data/spec/lib/backend/files_spec.rb +14 -24
  123. data/spec/lib/backend/redis/basic_spec.rb +2 -2
  124. data/spec/lib/backend/redis/list_hash_spec.rb +3 -3
  125. data/spec/lib/backend/redis/string_hash_spec.rb +3 -3
  126. data/spec/lib/backend/redis_spec.rb +20 -13
  127. data/spec/lib/calculations/location_spec.rb +1 -1
  128. data/spec/lib/categories_indexed_spec.rb +16 -34
  129. data/spec/lib/category_indexed_spec.rb +9 -27
  130. data/spec/lib/category_indexing_spec.rb +2 -3
  131. data/spec/lib/category_spec.rb +10 -10
  132. data/spec/lib/character_substituters/west_european_spec.rb +6 -5
  133. data/spec/lib/cores_spec.rb +17 -17
  134. data/spec/lib/extensions/symbol_spec.rb +15 -1
  135. data/spec/lib/frontend_adapters/rack_spec.rb +20 -20
  136. data/spec/lib/generators/aliases_spec.rb +3 -3
  137. data/spec/lib/generators/cacher_strategy_spec.rb +1 -1
  138. data/spec/lib/generators/partial/default_spec.rb +3 -3
  139. data/spec/lib/generators/partial/none_spec.rb +2 -2
  140. data/spec/lib/generators/partial/substring_spec.rb +1 -1
  141. data/spec/lib/generators/partial_generator_spec.rb +3 -3
  142. data/spec/lib/generators/similarity/double_metaphone_spec.rb +1 -1
  143. data/spec/lib/generators/similarity/metaphone_spec.rb +1 -1
  144. data/spec/lib/generators/similarity/none_spec.rb +1 -1
  145. data/spec/lib/generators/similarity/phonetic_spec.rb +1 -1
  146. data/spec/lib/generators/similarity/soundex_spec.rb +1 -1
  147. data/spec/lib/generators/similarity_generator_spec.rb +2 -2
  148. data/spec/lib/generators/weights/logarithmic_spec.rb +1 -1
  149. data/spec/lib/generators/weights_generator_spec.rb +1 -1
  150. data/spec/lib/helpers/measuring_spec.rb +2 -2
  151. data/spec/lib/indexed/bundle/memory_spec.rb +6 -6
  152. data/spec/lib/indexed/bundle/redis_spec.rb +4 -4
  153. data/spec/lib/indexed/wrappers/bundle/calculation_spec.rb +2 -3
  154. data/spec/lib/indexed/wrappers/bundle/wrapper_spec.rb +2 -2
  155. data/spec/lib/indexed/wrappers/exact_first_spec.rb +5 -5
  156. data/spec/lib/indexers/base_spec.rb +1 -1
  157. data/spec/lib/indexers/parallel_spec.rb +1 -1
  158. data/spec/lib/indexers/serial_spec.rb +1 -1
  159. data/spec/lib/{index/base_indexed_spec.rb → indexes/index_indexed_spec.rb} +3 -3
  160. data/spec/lib/{index/base_indexing_spec.rb → indexes/index_indexing_spec.rb} +19 -2
  161. data/spec/lib/{index/base_spec.rb → indexes/index_spec.rb} +6 -25
  162. data/spec/lib/{index → indexes}/redis_spec.rb +1 -1
  163. data/spec/lib/indexes_class_spec.rb +2 -2
  164. data/spec/lib/indexes_indexed_spec.rb +1 -1
  165. data/spec/lib/indexes_indexing_spec.rb +1 -1
  166. data/spec/lib/indexes_spec.rb +1 -1
  167. data/spec/lib/indexing/bundle/base_spec.rb +7 -5
  168. data/spec/lib/indexing/bundle/memory_partial_generation_speed_spec.rb +4 -4
  169. data/spec/lib/indexing/bundle/memory_spec.rb +15 -15
  170. data/spec/lib/indexing/bundle/redis_spec.rb +9 -9
  171. data/spec/lib/interfaces/live_parameters_spec.rb +5 -5
  172. data/spec/lib/loader_spec.rb +17 -19
  173. data/spec/lib/loggers/search_spec.rb +2 -2
  174. data/spec/lib/query/allocation_spec.rb +1 -1
  175. data/spec/lib/query/allocations_spec.rb +1 -1
  176. data/spec/lib/query/combination_spec.rb +4 -4
  177. data/spec/lib/query/combinations/base_spec.rb +1 -1
  178. data/spec/lib/query/combinations/memory_spec.rb +1 -1
  179. data/spec/lib/query/combinations/redis_spec.rb +1 -1
  180. data/spec/lib/query/indexes_spec.rb +7 -2
  181. data/spec/lib/query/qualifier_category_mapper_spec.rb +34 -0
  182. data/spec/lib/query/token_spec.rb +32 -53
  183. data/spec/lib/query/tokens_spec.rb +30 -35
  184. data/spec/lib/query/weights_spec.rb +16 -16
  185. data/spec/lib/rack/harakiri_spec.rb +5 -5
  186. data/spec/lib/results_spec.rb +1 -1
  187. data/spec/lib/search_spec.rb +24 -22
  188. data/spec/lib/sinatra_spec.rb +36 -0
  189. data/spec/lib/sources/base_spec.rb +1 -1
  190. data/spec/lib/sources/couch_spec.rb +9 -9
  191. data/spec/lib/sources/csv_spec.rb +7 -7
  192. data/spec/lib/sources/db_spec.rb +2 -2
  193. data/spec/lib/sources/delicious_spec.rb +5 -5
  194. data/spec/lib/sources/mongo_spec.rb +7 -7
  195. data/spec/lib/sources/wrappers/base_spec.rb +2 -2
  196. data/spec/lib/sources/wrappers/location_spec.rb +1 -1
  197. data/spec/lib/statistics_spec.rb +1 -1
  198. data/spec/lib/tokenizers/base_spec.rb +2 -2
  199. data/spec/lib/tokenizers/index_spec.rb +1 -1
  200. data/spec/lib/tokenizers/query_spec.rb +1 -1
  201. metadata +30 -30
  202. data/lib/picky/adapters/rack/query.rb +0 -65
  203. data/lib/picky/index/base.rb +0 -409
  204. data/lib/picky/index/base_indexed.rb +0 -29
  205. data/lib/picky/index/base_indexing.rb +0 -127
  206. data/lib/picky/index/memory.rb +0 -16
  207. data/lib/picky/index/redis.rb +0 -16
  208. data/lib/picky/query/qualifiers.rb +0 -76
  209. data/lib/picky/query/solr.rb +0 -60
  210. data/lib/picky/signals.rb +0 -8
  211. data/lib/picky-tasks.rb +0 -6
  212. data/lib/tasks/spec.rake +0 -11
  213. data/spec/lib/query/qualifiers_spec.rb +0 -31
@@ -1,44 +1,48 @@
1
- module Query
1
+ module Picky
2
2
 
3
- # Combinations are a number of Combination-s.
4
- #
5
- # They are the core of an allocation.
6
- # An allocation consists of a number of combinations.
7
- #
8
- module Combinations # :nodoc:all
3
+ module Query
9
4
 
10
- # Memory Combinations contain specific methods for
11
- # calculating score and ids in memory.
5
+ # Combinations are a number of Combination-s.
12
6
  #
13
- class Memory < Base
7
+ # They are the core of an allocation.
8
+ # An allocation consists of a number of combinations.
9
+ #
10
+ module Combinations # :nodoc:all
14
11
 
15
- # Returns the result ids for the allocation.
16
- #
17
- # Sorts the ids by size and & through them in the following order (sizes):
18
- # 0. [100_000, 400, 30, 2]
19
- # 1. [2, 30, 400, 100_000]
20
- # 2. (100_000 & (400 & (30 & 2))) # => result
21
- #
22
- # Note: Uses a C-optimized intersection routine (in performant.c)
23
- # for speed and memory efficiency.
12
+ # Memory Combinations contain specific methods for
13
+ # calculating score and ids in memory.
24
14
  #
25
- # Note: In the memory based version we ignore the (amount) needed hint.
26
- # We cannot use the information to speed up the algorithm, unfortunately.
27
- #
28
- def ids _, _
29
- return [] if @combinations.empty?
15
+ class Memory < Base
30
16
 
31
- # Get the ids for each combination.
17
+ # Returns the result ids for the allocation.
32
18
  #
33
- id_arrays = @combinations.inject([]) do |total, combination|
34
- total << combination.ids
35
- end
36
-
37
- # Call the optimized C algorithm.
19
+ # Sorts the ids by size and & through them in the following order (sizes):
20
+ # 0. [100_000, 400, 30, 2]
21
+ # 1. [2, 30, 400, 100_000]
22
+ # 2. (100_000 & (400 & (30 & 2))) # => result
23
+ #
24
+ # Note: Uses a C-optimized intersection routine (in performant.c)
25
+ # for speed and memory efficiency.
38
26
  #
39
- # Note: It orders the passed arrays by size.
27
+ # Note: In the memory based version we ignore the (amount) needed hint.
28
+ # We cannot use the information to speed up the algorithm, unfortunately.
40
29
  #
41
- Performant::Array.memory_efficient_intersect id_arrays
30
+ def ids _, _
31
+ return [] if @combinations.empty?
32
+
33
+ # Get the ids for each combination.
34
+ #
35
+ id_arrays = @combinations.inject([]) do |total, combination|
36
+ total << combination.ids
37
+ end
38
+
39
+ # Call the optimized C algorithm.
40
+ #
41
+ # Note: It orders the passed arrays by size.
42
+ #
43
+ Performant::Array.memory_efficient_intersect id_arrays
44
+ end
45
+
42
46
  end
43
47
 
44
48
  end
@@ -1,82 +1,86 @@
1
- module Query
1
+ module Picky
2
2
 
3
- # Combinations are a number of Combination-s.
4
- #
5
- # They are the core of an allocation.
6
- # An allocation consists of a number of combinations.
7
- #
8
- module Combinations # :nodoc:all
3
+ module Query
9
4
 
10
- # Redis Combinations contain specific methods for
11
- # calculating score and ids in memory.
5
+ # Combinations are a number of Combination-s.
12
6
  #
13
- class Redis < Base
7
+ # They are the core of an allocation.
8
+ # An allocation consists of a number of combinations.
9
+ #
10
+ module Combinations # :nodoc:all
14
11
 
15
- # Connect to the backend.
16
- #
17
- # TODO Use specific Picky Redis wrapper.
12
+ # Redis Combinations contain specific methods for
13
+ # calculating score and ids in memory.
18
14
  #
19
- def self.redis
20
- @redis ||= ::Redis.new :db => 15
21
- end
15
+ class Redis < Base
22
16
 
23
- attr_reader :redis
17
+ # Connect to the backend.
18
+ #
19
+ # TODO Use specific Picky Redis wrapper.
20
+ #
21
+ def self.redis
22
+ @redis ||= ::Redis.new :db => 15
23
+ end
24
24
 
25
- #
26
- #
27
- def initialize combinations
28
- super combinations
25
+ attr_reader :redis
29
26
 
30
- @redis = self.class.redis
31
- end
32
-
33
- # Returns the result ids for the allocation.
34
- #
35
- def ids amount, offset
36
- return [] if @combinations.empty?
27
+ #
28
+ #
29
+ def initialize combinations
30
+ super combinations
37
31
 
38
- identifiers = @combinations.inject([]) do |identifiers, combination|
39
- identifiers << "#{combination.identifier}"
32
+ @redis = self.class.redis
40
33
  end
41
34
 
42
- result_id = generate_intermediate_result_id
43
-
44
- # Intersect and store.
35
+ # Returns the result ids for the allocation.
45
36
  #
46
- redis.zinterstore result_id, identifiers
37
+ def ids amount, offset
38
+ return [] if @combinations.empty?
47
39
 
48
- # Get the stored result.
49
- #
50
- results = redis.zrange result_id, offset, (offset + amount)
40
+ identifiers = @combinations.inject([]) do |identifiers, combination|
41
+ identifiers << "#{combination.identifier}"
42
+ end
43
+
44
+ result_id = generate_intermediate_result_id
45
+
46
+ # Intersect and store.
47
+ #
48
+ redis.zinterstore result_id, identifiers
51
49
 
52
- # Delete the stored result as it was only for temporary purposes.
50
+ # Get the stored result.
51
+ #
52
+ results = redis.zrange result_id, offset, (offset + amount)
53
+
54
+ # Delete the stored result as it was only for temporary purposes.
55
+ #
56
+ # Note: I could also not delete it, but that would not be clean at all.
57
+ #
58
+ redis.del result_id
59
+
60
+ results
61
+ end
62
+
63
+ # Generate a multiple host/process safe result id.
53
64
  #
54
- # Note: I could also not delete it, but that would not be clean at all.
65
+ # Note: Generated when this class loads.
55
66
  #
56
- redis.del result_id
57
-
58
- results
59
- end
67
+ require 'socket'
68
+ def self.extract_host
69
+ @host ||= Socket.gethostname
70
+ end
71
+ def host
72
+ self.class.extract_host
73
+ end
74
+ extract_host
75
+ def pid
76
+ @pid ||= Process.pid
77
+ end
78
+ # Use the host and pid (generated lazily in child processes) for the result.
79
+ #
80
+ def generate_intermediate_result_id
81
+ :"#{host}:#{pid}:picky:result"
82
+ end
60
83
 
61
- # Generate a multiple host/process safe result id.
62
- #
63
- # Note: Generated when this class loads.
64
- #
65
- require 'socket'
66
- def self.extract_host
67
- @host ||= Socket.gethostname
68
- end
69
- def host
70
- self.class.extract_host
71
- end
72
- extract_host
73
- def pid
74
- @pid ||= Process.pid
75
- end
76
- # Use the host and pid (generated lazily in child processes) for the result.
77
- #
78
- def generate_intermediate_result_id
79
- :"#{host}:#{pid}:picky:result"
80
84
  end
81
85
 
82
86
  end
@@ -1,193 +1,208 @@
1
- module Query
2
-
3
- # The query indexes class bundles indexes given to a query.
4
- #
5
- # Example:
6
- # # If you call
7
- # Search.new dvd_index, mp3_index, video_index
8
- #
9
- # # What it does is take the three given (API-) indexes and
10
- # # bundle them in an index bundle.
11
- #
12
- class Indexes
13
-
14
- attr_reader :indexes
15
-
16
- # Creates a new Query::Indexes.
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ # The query indexes class bundles indexes given to a query.
17
6
  #
18
- # Its job is to generate all possible combinations.
19
- # Note: We cannot mix memory and redis indexes just yet.
7
+ # Example:
8
+ # # If you call
9
+ # Search.new dvd_index, mp3_index, video_index
20
10
  #
21
- def initialize *indexes, combinations_type
22
- @indexes = indexes
23
- @combinations_type = combinations_type
24
- end
25
-
26
- # Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
11
+ # # What it does is take the three given (API-) indexes and
12
+ # # bundle them in an index bundle.
27
13
  #
28
- def prepared_allocations_for tokens, weights = {}
29
- allocations = allocations_for tokens
14
+ class Indexes
30
15
 
31
- # Remove double allocations.
32
- #
33
- allocations.uniq
16
+ attr_reader :indexes
34
17
 
35
- # Score the allocations using weights as bias.
18
+ # Creates a new Query::Indexes.
36
19
  #
37
- allocations.calculate_score weights
38
-
39
- # Sort the allocations.
40
- # (allocations are sorted according to score, highest to lowest)
20
+ # Its job is to generate all possible combinations.
21
+ # Note: We cannot mix memory and redis indexes just yet.
41
22
  #
42
- allocations.sort!
23
+ def initialize *indexes, combinations_type
24
+ @indexes = indexes
25
+ @combinations_type = combinations_type
26
+ @mapper = Query::QualifierCategoryMapper.new
27
+ map_categories
28
+ end
29
+ def map_categories
30
+ @indexes.each do |index|
31
+ index.each_category do |category|
32
+ @mapper.add category
33
+ end
34
+ end
35
+ end
43
36
 
44
- # Reduce the amount of allocations.
37
+ # Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
45
38
  #
46
- # allocations.reduce_to some_amount
39
+ def prepared_allocations_for tokens, weights = {}
40
+ allocations = allocations_for tokens
47
41
 
48
- # Remove identifiers from allocations.
49
- #
50
- # allocations.remove some_array_of_identifiers_to_remove
42
+ # Remove double allocations.
43
+ #
44
+ allocations.uniq
51
45
 
52
- allocations
53
- end
54
- # Returns a number of possible allocations for the given tokens.
55
- #
56
- def allocations_for tokens
57
- Allocations.new allocations_ary_for(tokens)
58
- end
59
- def allocations_ary_for tokens
60
- indexes.inject([]) do |allocations, index|
61
- allocations + allocation_for(tokens, index)
62
- end
63
- end
64
- def allocation_for tokens, index
65
- # Expand the combinations.
66
- #
67
- possible_combinations = tokens.possible_combinations_in index
46
+ # Score the allocations using weights as bias.
47
+ #
48
+ allocations.calculate_score weights
68
49
 
69
- # Generate all possible combinations.
70
- #
71
- expanded_combinations = expand_combinations_from possible_combinations
50
+ # Sort the allocations.
51
+ # (allocations are sorted according to score, highest to lowest)
52
+ #
53
+ allocations.sort!
72
54
 
73
- # Add the wrapped possible allocations to the ones we already have.
74
- #
75
- expanded_combinations.map! do |expanded_combination|
76
- Allocation.new @combinations_type.new(expanded_combination), index.result_identifier # TODO Do not extract result_identifier.
77
- end
78
- end
55
+ # Reduce the amount of allocations.
56
+ #
57
+ # allocations.reduce_to some_amount
79
58
 
80
- # This is the core of the search engine. No kidding.
81
- #
82
- # Gets an array of
83
- # [
84
- # [<combinations for token1>],
85
- # [<combinations for token2>],
86
- # [<combinations for token3>]
87
- # ]
88
- #
89
- # Generates all possible allocations of combinations.
90
- # [
91
- # [first combination of token1, first c of t2, first c of t3],
92
- # [first combination of token1, first c of t2, second c of t3]
93
- # ...
94
- # ]
95
- #
96
- # Generates all possible combinations of array elements:
97
- # [1,2,3] x [a,b,c] x [k,l,m] => [[1,a,k], [1,a,l], [1,a,m], [1,b,k], [1,b,l], [1,b,m], [1,c,k], ..., [3,c,m]]
98
- # Note: Also calculates the weights and sorts them accordingly.
99
- #
100
- # Note: This is a heavily optimized ruby version.
101
- #
102
- # Works like this:
103
- # [1,2,3], [a,b,c], [k,l,m] are expanded to
104
- # group mult: 1
105
- # <- single mult ->
106
- # [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3] = 27 elements
107
- # group mult: 3
108
- # <- -> s/m
109
- # [a,a,a,b,b,b,c,c,c,a,a,a,b,b,b,c,c,c,a,a,a,b,b,b,c,c,c] = 27 elements
110
- # group mult: 9
111
- # <> s/m
112
- # [k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m] = 27 elements
113
- #
114
- # It is then recombined, where
115
- # [
116
- # [a,a,b,b,c,c]
117
- # [d,e,d,e,d,e]
118
- # ]
119
- # becomes
120
- # [
121
- # [a,d],
122
- # [a,e],
123
- # [b,d],
124
- # [b,e],
125
- # [c,d],
126
- # [c,e]
127
- # ]
128
- #
129
- # Note: Not using transpose as it is slower.
130
- #
131
- # Returns nil if there are no combinations.
132
- #
133
- # Note: Of course I could split this method up into smaller
134
- # ones, but I guess I am a bit sentimental.
135
- #
136
- def expand_combinations_from possible_combinations
137
- # If an element has size 0, this means one of the
138
- # tokens could not be allocated.
139
- #
140
- return [] if possible_combinations.any?(&:empty?)
59
+ # Remove identifiers from allocations.
60
+ #
61
+ # allocations.remove some_array_of_identifiers_to_remove
141
62
 
142
- # Generate the first multiplicator "with which" (well, not quite) to multiply the smallest amount of combinations.
63
+ allocations
64
+ end
65
+ # Returns a number of possible allocations for the given tokens.
143
66
  #
144
- single_mult = possible_combinations.inject(1) { |total, combinations| total * combinations.size }
67
+ def allocations_for tokens
68
+ tokens.categorize @mapper
145
69
 
146
- # Initialize a group multiplicator.
147
- #
148
- group_mult = 1
70
+ Allocations.new allocations_ary_for(tokens)
71
+ end
72
+ def allocations_ary_for tokens
73
+ indexes.inject([]) do |allocations, index|
74
+ allocations + allocation_for(tokens, index)
75
+ end
76
+ end
77
+ def allocation_for tokens, index
78
+ # Expand the combinations.
79
+ #
80
+ possible_combinations = tokens.possible_combinations_in index
149
81
 
150
- # The expanding part to line up the combinations
151
- # for later combination in allocations.
152
- #
153
- possible_combinations.collect! do |combinations|
82
+ # Generate all possible combinations.
83
+ #
84
+ expanded_combinations = expand_combinations_from possible_combinations
154
85
 
155
- # Get the size of the combinations of the first token.
86
+ # Add the wrapped possible allocations to the ones we already have.
156
87
  #
157
- combinations_size = combinations.size
88
+ expanded_combinations.map! do |expanded_combination|
89
+ Allocation.new @combinations_type.new(expanded_combination), index.result_identifier # TODO Do not extract result_identifier.
90
+ end
91
+ end
158
92
 
159
- # Special case: If there is no combination for one of the tokens.
160
- # In that case, we just use the same single mult for
161
- # the next iteration.
162
- # If there are combinations, we divide the single mult
163
- # by the number of combinations.
93
+ # This is the core of the search engine. No kidding.
94
+ #
95
+ # Gets an array of
96
+ # [
97
+ # [<combinations for token1>],
98
+ # [<combinations for token2>],
99
+ # [<combinations for token3>]
100
+ # ]
101
+ #
102
+ # Generates all possible allocations of combinations.
103
+ # [
104
+ # [first combination of token1, first c of t2, first c of t3],
105
+ # [first combination of token1, first c of t2, second c of t3]
106
+ # ...
107
+ # ]
108
+ #
109
+ # Generates all possible combinations of array elements:
110
+ # [1,2,3] x [a,b,c] x [k,l,m] => [[1,a,k], [1,a,l], [1,a,m], [1,b,k], [1,b,l], [1,b,m], [1,c,k], ..., [3,c,m]]
111
+ # Note: Also calculates the weights and sorts them accordingly.
112
+ #
113
+ # Note: This is a heavily optimized ruby version.
114
+ #
115
+ # Works like this:
116
+ # [1,2,3], [a,b,c], [k,l,m] are expanded to
117
+ # group mult: 1
118
+ # <- single mult ->
119
+ # [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3] = 27 elements
120
+ # group mult: 3
121
+ # <- -> s/m
122
+ # [a,a,a,b,b,b,c,c,c,a,a,a,b,b,b,c,c,c,a,a,a,b,b,b,c,c,c] = 27 elements
123
+ # group mult: 9
124
+ # <> s/m
125
+ # [k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m,k,l,m] = 27 elements
126
+ #
127
+ # It is then recombined, where
128
+ # [
129
+ # [a,a,b,b,c,c]
130
+ # [d,e,d,e,d,e]
131
+ # ]
132
+ # becomes
133
+ # [
134
+ # [a,d],
135
+ # [a,e],
136
+ # [b,d],
137
+ # [b,e],
138
+ # [c,d],
139
+ # [c,e]
140
+ # ]
141
+ #
142
+ # Note: Not using transpose as it is slower.
143
+ #
144
+ # Returns nil if there are no combinations.
145
+ #
146
+ # Note: Of course I could split this method up into smaller
147
+ # ones, but I guess I am a bit sentimental.
148
+ #
149
+ def expand_combinations_from possible_combinations
150
+ # If an element has size 0, this means one of the
151
+ # tokens could not be allocated.
164
152
  #
165
- single_mult /= combinations_size unless combinations_size.zero?
153
+ return [] if possible_combinations.any?(&:empty?)
166
154
 
167
- # Expand each combination by the single mult:
168
- # [a,b,c]
169
- # [a,a,a, b,b,b, c,c,c]
170
- # Then, expand the result by the group mult:
171
- # [a,a,a,b,b,b,c,c,c, a,a,a,b,b,b,c,c,c, a,a,a,b,b,b,c,c,c]
155
+ # Generate the first multiplicator "with which" (well, not quite) to multiply the smallest amount of combinations.
172
156
  #
173
- combinations = combinations.inject([]) do |total, combination|
174
- total + Array.new(single_mult, combination)
175
- end * group_mult
157
+ single_mult = possible_combinations.inject(1) { |total, combinations| total * combinations.size }
176
158
 
177
- # Multiply the group mult by the combinations size,
178
- # since the next combinations' single mult is smaller
179
- # and we need to adjust for that.
159
+ # Initialize a group multiplicator.
180
160
  #
181
- group_mult = group_mult * combinations_size
161
+ group_mult = 1
182
162
 
183
- # Return the combinations.
163
+ # The expanding part to line up the combinations
164
+ # for later combination in allocations.
184
165
  #
185
- combinations
166
+ possible_combinations.collect! do |combinations|
167
+
168
+ # Get the size of the combinations of the first token.
169
+ #
170
+ combinations_size = combinations.size
171
+
172
+ # Special case: If there is no combination for one of the tokens.
173
+ # In that case, we just use the same single mult for
174
+ # the next iteration.
175
+ # If there are combinations, we divide the single mult
176
+ # by the number of combinations.
177
+ #
178
+ single_mult /= combinations_size unless combinations_size.zero?
179
+
180
+ # Expand each combination by the single mult:
181
+ # [a,b,c]
182
+ # [a,a,a, b,b,b, c,c,c]
183
+ # Then, expand the result by the group mult:
184
+ # [a,a,a,b,b,b,c,c,c, a,a,a,b,b,b,c,c,c, a,a,a,b,b,b,c,c,c]
185
+ #
186
+ combinations = combinations.inject([]) do |total, combination|
187
+ total + Array.new(single_mult, combination)
188
+ end * group_mult
189
+
190
+ # Multiply the group mult by the combinations size,
191
+ # since the next combinations' single mult is smaller
192
+ # and we need to adjust for that.
193
+ #
194
+ group_mult = group_mult * combinations_size
195
+
196
+ # Return the combinations.
197
+ #
198
+ combinations
199
+ end
200
+
201
+ return [] if possible_combinations.empty?
202
+
203
+ possible_combinations.shift.zip *possible_combinations
186
204
  end
187
205
 
188
- return [] if possible_combinations.empty?
189
-
190
- possible_combinations.shift.zip *possible_combinations
191
206
  end
192
207
 
193
208
  end
@@ -0,0 +1,43 @@
1
+ module Picky
2
+
3
+ # coding: utf-8
4
+ #
5
+ module Query
6
+
7
+ # Collection class for qualifiers.
8
+ #
9
+ class QualifierCategoryMapper # :nodoc:all
10
+
11
+ attr_reader :mapping
12
+
13
+ #
14
+ #
15
+ def initialize
16
+ @mapping = {}
17
+ end
18
+
19
+ #
20
+ #
21
+ def add category
22
+ category.qualifiers.each do |qualifier|
23
+ sym_qualifier = qualifier.to_sym
24
+ warn %Q{Warning: Qualifier "#{qualifier}" already mapped to category #{mapping[sym_qualifier].identifier} (ambiguous qualifier mapping).} if mapping.has_key? sym_qualifier
25
+ mapping[sym_qualifier] = category
26
+ end
27
+ end
28
+
29
+ # Normalizes the given qualifier.
30
+ #
31
+ # Returns nil if it is not allowed, the normalized qualifier if it is.
32
+ #
33
+ def map qualifier
34
+ return nil if qualifier.blank?
35
+
36
+ @mapping[qualifier.to_sym]
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end