picky 2.5.2 → 2.6.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 (255) hide show
  1. data/lib/picky/adapters/rack/base.rb +23 -0
  2. data/lib/picky/adapters/rack/live_parameters.rb +33 -0
  3. data/lib/picky/adapters/rack/query.rb +65 -0
  4. data/lib/picky/adapters/rack.rb +30 -0
  5. data/lib/picky/application.rb +5 -5
  6. data/lib/picky/backend/backend.rb +108 -0
  7. data/lib/picky/backend/file/basic.rb +101 -0
  8. data/lib/picky/backend/file/json.rb +34 -0
  9. data/lib/picky/backend/file/marshal.rb +34 -0
  10. data/lib/picky/backend/file/text.rb +56 -0
  11. data/lib/picky/backend/files.rb +30 -0
  12. data/lib/picky/backend/redis/basic.rb +85 -0
  13. data/lib/picky/backend/redis/list_hash.rb +49 -0
  14. data/lib/picky/backend/redis/string_hash.rb +40 -0
  15. data/lib/picky/backend/redis.rb +40 -0
  16. data/lib/picky/calculations/location.rb +57 -0
  17. data/lib/picky/categories.rb +62 -0
  18. data/lib/picky/categories_indexed.rb +93 -0
  19. data/lib/picky/categories_indexing.rb +12 -0
  20. data/lib/picky/category.rb +127 -0
  21. data/lib/picky/category_indexed.rb +64 -0
  22. data/lib/picky/category_indexing.rb +145 -0
  23. data/lib/picky/{internals/ext → ext}/maybe_compile.rb +0 -0
  24. data/lib/picky/{internals/ext → ext}/ruby19/extconf.rb +0 -0
  25. data/lib/picky/{internals/ext → ext}/ruby19/performant.c +0 -0
  26. data/lib/picky/{internals/extensions → extensions}/array.rb +0 -0
  27. data/lib/picky/extensions/class.rb +11 -0
  28. data/lib/picky/{internals/extensions → extensions}/hash.rb +0 -0
  29. data/lib/picky/{internals/extensions → extensions}/module.rb +0 -0
  30. data/lib/picky/{internals/extensions → extensions}/object.rb +0 -0
  31. data/lib/picky/{internals/extensions → extensions}/symbol.rb +0 -0
  32. data/lib/picky/frontend_adapters/rack.rb +146 -0
  33. data/lib/picky/generators/aliases.rb +3 -3
  34. data/lib/picky/generators/base.rb +15 -0
  35. data/lib/picky/generators/partial/default.rb +5 -0
  36. data/lib/picky/generators/partial/none.rb +31 -0
  37. data/lib/picky/generators/partial/strategy.rb +25 -0
  38. data/lib/picky/generators/partial/substring.rb +118 -0
  39. data/lib/picky/generators/partial_generator.rb +15 -0
  40. data/lib/picky/generators/similarity/default.rb +7 -0
  41. data/lib/picky/generators/similarity/double_metaphone.rb +28 -0
  42. data/lib/picky/generators/similarity/metaphone.rb +28 -0
  43. data/lib/picky/generators/similarity/none.rb +31 -0
  44. data/lib/picky/generators/similarity/phonetic.rb +65 -0
  45. data/lib/picky/generators/similarity/soundex.rb +28 -0
  46. data/lib/picky/generators/similarity/strategy.rb +9 -0
  47. data/lib/picky/generators/similarity_generator.rb +15 -0
  48. data/lib/picky/generators/strategy.rb +14 -0
  49. data/lib/picky/generators/weights/default.rb +7 -0
  50. data/lib/picky/generators/weights/logarithmic.rb +39 -0
  51. data/lib/picky/generators/weights/strategy.rb +9 -0
  52. data/lib/picky/generators/weights_generator.rb +15 -0
  53. data/lib/picky/{internals/helpers → helpers}/measuring.rb +0 -0
  54. data/lib/picky/index/base.rb +119 -104
  55. data/lib/picky/index/base_indexed.rb +27 -0
  56. data/lib/picky/index/base_indexing.rb +119 -0
  57. data/lib/picky/index/memory.rb +6 -18
  58. data/lib/picky/index/redis.rb +6 -18
  59. data/lib/picky/indexed/bundle/base.rb +110 -0
  60. data/lib/picky/indexed/bundle/memory.rb +91 -0
  61. data/lib/picky/indexed/bundle/redis.rb +45 -0
  62. data/lib/picky/indexed/wrappers/bundle/calculation.rb +35 -0
  63. data/lib/picky/indexed/wrappers/bundle/location.rb +42 -0
  64. data/lib/picky/indexed/wrappers/bundle/wrapper.rb +43 -0
  65. data/lib/picky/indexed/wrappers/category/location.rb +25 -0
  66. data/lib/picky/indexed/wrappers/exact_first.rb +55 -0
  67. data/lib/picky/{internals/indexers → indexers}/base.rb +0 -0
  68. data/lib/picky/{internals/indexers → indexers}/parallel.rb +0 -0
  69. data/lib/picky/{internals/indexers → indexers}/serial.rb +0 -0
  70. data/lib/picky/{internals/indexers → indexers}/solr.rb +0 -0
  71. data/lib/picky/indexes.rb +73 -0
  72. data/lib/picky/indexes_indexed.rb +29 -0
  73. data/lib/picky/indexes_indexing.rb +49 -0
  74. data/lib/picky/indexing/bundle/base.rb +212 -0
  75. data/lib/picky/indexing/bundle/memory.rb +25 -0
  76. data/lib/picky/indexing/bundle/redis.rb +24 -0
  77. data/lib/picky/indexing/bundle/super_base.rb +61 -0
  78. data/lib/picky/indexing/wrappers/category/location.rb +25 -0
  79. data/lib/picky/interfaces/live_parameters.rb +8 -8
  80. data/lib/picky/loader.rb +89 -95
  81. data/lib/picky/{internals/performant.rb → performant.rb} +0 -0
  82. data/lib/picky/query/allocation.rb +84 -0
  83. data/lib/picky/query/allocations.rb +114 -0
  84. data/lib/picky/query/combination.rb +76 -0
  85. data/lib/picky/query/combinations/base.rb +70 -0
  86. data/lib/picky/query/combinations/memory.rb +48 -0
  87. data/lib/picky/query/combinations/redis.rb +86 -0
  88. data/lib/picky/query/indexes.rb +195 -0
  89. data/lib/picky/query/qualifiers.rb +76 -0
  90. data/lib/picky/query/token.rb +198 -0
  91. data/lib/picky/query/tokens.rb +103 -0
  92. data/lib/picky/{internals/query → query}/weights.rb +0 -0
  93. data/lib/picky/results.rb +1 -1
  94. data/lib/picky/search.rb +6 -6
  95. data/lib/picky/{internals/solr → solr}/schema_generator.rb +0 -0
  96. data/lib/picky/sources/db.rb +7 -7
  97. data/lib/picky/sources/wrappers/location.rb +2 -2
  98. data/lib/picky/tokenizers/base.rb +224 -0
  99. data/lib/picky/tokenizers/index.rb +30 -0
  100. data/lib/picky/tokenizers/location.rb +49 -0
  101. data/lib/picky/tokenizers/query.rb +55 -0
  102. data/lib/tasks/index.rake +4 -3
  103. data/lib/tasks/try.rake +2 -2
  104. data/spec/lib/{internals/adapters → adapters}/rack/base_spec.rb +1 -1
  105. data/spec/lib/{internals/adapters → adapters}/rack/live_parameters_spec.rb +1 -1
  106. data/spec/lib/{internals/adapters → adapters}/rack/query_spec.rb +1 -1
  107. data/spec/lib/application_spec.rb +3 -3
  108. data/spec/lib/{internals/index → backend}/file/basic_spec.rb +1 -1
  109. data/spec/lib/{internals/index → backend}/file/json_spec.rb +1 -1
  110. data/spec/lib/{internals/index → backend}/file/marshal_spec.rb +1 -1
  111. data/spec/lib/{internals/index → backend}/file/text_spec.rb +1 -1
  112. data/spec/lib/{internals/index → backend}/files_spec.rb +3 -3
  113. data/spec/lib/{internals/index → backend}/redis/basic_spec.rb +1 -1
  114. data/spec/lib/{internals/index → backend}/redis/list_hash_spec.rb +1 -1
  115. data/spec/lib/{internals/index → backend}/redis/string_hash_spec.rb +1 -1
  116. data/spec/lib/{internals/index → backend}/redis_spec.rb +11 -5
  117. data/spec/lib/{internals/calculations → calculations}/location_spec.rb +1 -1
  118. data/spec/lib/{internals/indexed/categories_spec.rb → categories_indexed_spec.rb} +10 -10
  119. data/spec/lib/{internals/indexed/category_spec.rb → category_indexed_spec.rb} +12 -12
  120. data/spec/lib/{internals/indexing/category_spec.rb → category_indexing_spec.rb} +10 -10
  121. data/spec/lib/{internals/cores_spec.rb → cores_spec.rb} +0 -0
  122. data/spec/lib/{internals/extensions → extensions}/array_spec.rb +0 -0
  123. data/spec/lib/{internals/extensions → extensions}/hash_spec.rb +0 -0
  124. data/spec/lib/{internals/extensions → extensions}/module_spec.rb +0 -0
  125. data/spec/lib/{internals/extensions → extensions}/object_spec.rb +0 -0
  126. data/spec/lib/{internals/extensions → extensions}/symbol_spec.rb +0 -0
  127. data/spec/lib/{internals/frontend_adapters → frontend_adapters}/rack_spec.rb +10 -10
  128. data/spec/lib/generators/aliases_spec.rb +3 -3
  129. data/spec/lib/{internals/generators → generators}/cacher_strategy_spec.rb +1 -1
  130. data/spec/lib/{internals/generators → generators}/partial/default_spec.rb +3 -3
  131. data/spec/lib/{internals/generators → generators}/partial/none_spec.rb +2 -2
  132. data/spec/lib/{internals/generators → generators}/partial/substring_spec.rb +1 -1
  133. data/spec/lib/{internals/generators → generators}/partial_generator_spec.rb +3 -3
  134. data/spec/lib/{internals/generators → generators}/similarity/double_metaphone_spec.rb +1 -1
  135. data/spec/lib/{internals/generators → generators}/similarity/metaphone_spec.rb +1 -1
  136. data/spec/lib/{internals/generators → generators}/similarity/none_spec.rb +1 -1
  137. data/spec/lib/{internals/generators → generators}/similarity/phonetic_spec.rb +1 -1
  138. data/spec/lib/{internals/generators → generators}/similarity/soundex_spec.rb +1 -1
  139. data/spec/lib/{internals/generators → generators}/similarity_generator_spec.rb +2 -2
  140. data/spec/lib/{internals/generators → generators}/weights/logarithmic_spec.rb +1 -1
  141. data/spec/lib/{internals/generators → generators}/weights_generator_spec.rb +5 -5
  142. data/spec/lib/{internals/helpers → helpers}/measuring_spec.rb +0 -0
  143. data/spec/lib/{internals/indexed/index_spec.rb → index/base_indexed_spec.rb} +5 -5
  144. data/spec/lib/{internals/indexing/index_spec.rb → index/base_indexing_spec.rb} +6 -19
  145. data/spec/lib/index/base_spec.rb +10 -53
  146. data/spec/lib/{internals/indexed → indexed}/bundle/memory_spec.rb +5 -5
  147. data/spec/lib/{internals/indexed → indexed}/bundle/redis_spec.rb +4 -4
  148. data/spec/lib/{internals/indexed → indexed}/wrappers/bundle/calculation_spec.rb +1 -1
  149. data/spec/lib/{internals/indexed → indexed}/wrappers/bundle/wrapper_spec.rb +1 -1
  150. data/spec/lib/{internals/indexed → indexed}/wrappers/exact_first_spec.rb +7 -7
  151. data/spec/lib/{internals/indexers → indexers}/base_spec.rb +0 -0
  152. data/spec/lib/{internals/indexers → indexers}/parallel_spec.rb +0 -0
  153. data/spec/lib/{internals/indexers → indexers}/serial_spec.rb +0 -0
  154. data/spec/lib/indexes_class_spec.rb +30 -0
  155. data/spec/lib/{indexed/indexes_spec.rb → indexes_indexed_spec.rb} +1 -1
  156. data/spec/lib/{indexing/indexes_spec.rb → indexes_indexing_spec.rb} +8 -8
  157. data/spec/lib/{internals/indexing/indexes_spec.rb → indexes_spec.rb} +15 -12
  158. data/spec/lib/{internals/indexing → indexing}/bundle/memory_partial_generation_speed_spec.rb +4 -4
  159. data/spec/lib/{internals/indexing → indexing}/bundle/memory_spec.rb +3 -3
  160. data/spec/lib/{internals/indexing → indexing}/bundle/redis_spec.rb +3 -3
  161. data/spec/lib/{internals/indexing → indexing}/bundle/super_base_spec.rb +2 -2
  162. data/spec/lib/{internals/interfaces → interfaces}/live_parameters_spec.rb +0 -0
  163. data/spec/lib/query/allocation_spec.rb +1 -1
  164. data/spec/lib/query/allocations_spec.rb +1 -1
  165. data/spec/lib/query/combination_spec.rb +5 -5
  166. data/spec/lib/query/combinations/base_spec.rb +1 -1
  167. data/spec/lib/query/combinations/memory_spec.rb +1 -1
  168. data/spec/lib/query/combinations/redis_spec.rb +1 -1
  169. data/spec/lib/query/indexes_spec.rb +1 -1
  170. data/spec/lib/query/qualifiers_spec.rb +4 -4
  171. data/spec/lib/query/token_spec.rb +3 -3
  172. data/spec/lib/query/tokens_spec.rb +32 -32
  173. data/spec/lib/search_spec.rb +5 -5
  174. data/spec/lib/{internals/solr → solr}/schema_generator_spec.rb +0 -0
  175. data/spec/lib/sources/db_spec.rb +4 -8
  176. data/spec/lib/sources/wrappers/location_spec.rb +1 -1
  177. data/spec/lib/{internals/tokenizers → tokenizers}/base_spec.rb +1 -1
  178. data/spec/lib/{internals/tokenizers → tokenizers}/index_spec.rb +1 -1
  179. data/spec/lib/{internals/tokenizers → tokenizers}/query_spec.rb +1 -1
  180. metadata +214 -215
  181. data/lib/picky/aliases.rb +0 -4
  182. data/lib/picky/index_bundle.rb +0 -48
  183. data/lib/picky/indexed/indexes.rb +0 -59
  184. data/lib/picky/indexing/indexes.rb +0 -87
  185. data/lib/picky/internals/adapters/rack/base.rb +0 -27
  186. data/lib/picky/internals/adapters/rack/live_parameters.rb +0 -37
  187. data/lib/picky/internals/adapters/rack/query.rb +0 -69
  188. data/lib/picky/internals/adapters/rack.rb +0 -34
  189. data/lib/picky/internals/calculations/location.rb +0 -59
  190. data/lib/picky/internals/frontend_adapters/rack.rb +0 -150
  191. data/lib/picky/internals/generators/base.rb +0 -19
  192. data/lib/picky/internals/generators/partial/default.rb +0 -7
  193. data/lib/picky/internals/generators/partial/none.rb +0 -35
  194. data/lib/picky/internals/generators/partial/strategy.rb +0 -29
  195. data/lib/picky/internals/generators/partial/substring.rb +0 -122
  196. data/lib/picky/internals/generators/partial_generator.rb +0 -19
  197. data/lib/picky/internals/generators/similarity/default.rb +0 -9
  198. data/lib/picky/internals/generators/similarity/double_metaphone.rb +0 -32
  199. data/lib/picky/internals/generators/similarity/metaphone.rb +0 -32
  200. data/lib/picky/internals/generators/similarity/none.rb +0 -35
  201. data/lib/picky/internals/generators/similarity/phonetic.rb +0 -69
  202. data/lib/picky/internals/generators/similarity/soundex.rb +0 -32
  203. data/lib/picky/internals/generators/similarity/strategy.rb +0 -11
  204. data/lib/picky/internals/generators/similarity_generator.rb +0 -19
  205. data/lib/picky/internals/generators/strategy.rb +0 -18
  206. data/lib/picky/internals/generators/weights/default.rb +0 -9
  207. data/lib/picky/internals/generators/weights/logarithmic.rb +0 -43
  208. data/lib/picky/internals/generators/weights/strategy.rb +0 -11
  209. data/lib/picky/internals/generators/weights_generator.rb +0 -19
  210. data/lib/picky/internals/index/backend.rb +0 -112
  211. data/lib/picky/internals/index/file/basic.rb +0 -105
  212. data/lib/picky/internals/index/file/json.rb +0 -38
  213. data/lib/picky/internals/index/file/marshal.rb +0 -38
  214. data/lib/picky/internals/index/file/text.rb +0 -60
  215. data/lib/picky/internals/index/files.rb +0 -34
  216. data/lib/picky/internals/index/redis/basic.rb +0 -89
  217. data/lib/picky/internals/index/redis/list_hash.rb +0 -53
  218. data/lib/picky/internals/index/redis/string_hash.rb +0 -44
  219. data/lib/picky/internals/index/redis.rb +0 -44
  220. data/lib/picky/internals/indexed/bundle/base.rb +0 -114
  221. data/lib/picky/internals/indexed/bundle/memory.rb +0 -95
  222. data/lib/picky/internals/indexed/bundle/redis.rb +0 -49
  223. data/lib/picky/internals/indexed/categories.rb +0 -140
  224. data/lib/picky/internals/indexed/category.rb +0 -111
  225. data/lib/picky/internals/indexed/index.rb +0 -63
  226. data/lib/picky/internals/indexed/wrappers/bundle/calculation.rb +0 -37
  227. data/lib/picky/internals/indexed/wrappers/bundle/location.rb +0 -44
  228. data/lib/picky/internals/indexed/wrappers/bundle/wrapper.rb +0 -45
  229. data/lib/picky/internals/indexed/wrappers/category/location.rb +0 -27
  230. data/lib/picky/internals/indexed/wrappers/exact_first.rb +0 -59
  231. data/lib/picky/internals/indexing/bundle/base.rb +0 -216
  232. data/lib/picky/internals/indexing/bundle/memory.rb +0 -29
  233. data/lib/picky/internals/indexing/bundle/redis.rb +0 -28
  234. data/lib/picky/internals/indexing/bundle/super_base.rb +0 -65
  235. data/lib/picky/internals/indexing/category.rb +0 -153
  236. data/lib/picky/internals/indexing/index.rb +0 -142
  237. data/lib/picky/internals/indexing/wrappers/category/location.rb +0 -27
  238. data/lib/picky/internals/query/allocation.rb +0 -88
  239. data/lib/picky/internals/query/allocations.rb +0 -118
  240. data/lib/picky/internals/query/combination.rb +0 -80
  241. data/lib/picky/internals/query/combinations/base.rb +0 -74
  242. data/lib/picky/internals/query/combinations/memory.rb +0 -52
  243. data/lib/picky/internals/query/combinations/redis.rb +0 -90
  244. data/lib/picky/internals/query/indexes.rb +0 -199
  245. data/lib/picky/internals/query/qualifiers.rb +0 -82
  246. data/lib/picky/internals/query/token.rb +0 -202
  247. data/lib/picky/internals/query/tokens.rb +0 -109
  248. data/lib/picky/internals/shared/category.rb +0 -52
  249. data/lib/picky/internals/tokenizers/base.rb +0 -228
  250. data/lib/picky/internals/tokenizers/index.rb +0 -34
  251. data/lib/picky/internals/tokenizers/location.rb +0 -54
  252. data/lib/picky/internals/tokenizers/query.rb +0 -59
  253. data/lib/picky/internals.rb +0 -2
  254. data/spec/lib/aliases_spec.rb +0 -9
  255. data/spec/lib/index_bundle_spec.rb +0 -69
@@ -1,74 +0,0 @@
1
- module Internals
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
- module Combinations # :nodoc:all
11
-
12
- # Base Combinations contain methods for calculating score and ids.
13
- #
14
- class Base
15
-
16
- attr_reader :combinations
17
-
18
- delegate :empty?, :to => :@combinations
19
-
20
- def initialize combinations = []
21
- @combinations = combinations
22
- end
23
-
24
- def hash
25
- @combinations.hash
26
- end
27
-
28
- # Uses user specific weights to calculate a score for the combinations.
29
- #
30
- def calculate_score weights
31
- total_score + weighted_score(weights)
32
- end
33
- def total_score
34
- @combinations.sum &:weight
35
- end
36
- def weighted_score weights
37
- weights.score @combinations
38
- end
39
-
40
- # Filters the tokens and identifiers such that only identifiers
41
- # that are passed in, remain, including their tokens.
42
- #
43
- # Note: This method is not totally independent of the calculate_ids one.
44
- # Since identifiers are only nullified, we need to not include the
45
- # ids that have an associated identifier that is nil.
46
- #
47
- def keep identifiers = []
48
- @combinations.reject! { |combination| !combination.in?(identifiers) }
49
- end
50
-
51
- # Filters the tokens and identifiers such that identifiers
52
- # that are passed in, are removed, including their tokens.
53
- #
54
- # Note: This method is not totally independent of the calculate_ids one.
55
- # Since identifiers are only nullified, we need to not include the
56
- # ids that have an associated identifier that is nil.
57
- #
58
- def remove identifiers = []
59
- @combinations.reject! { |combination| combination.in?(identifiers) }
60
- end
61
-
62
- #
63
- #
64
- def to_result
65
- @combinations.map &:to_result
66
- end
67
-
68
- end
69
-
70
- end
71
-
72
- end
73
-
74
- end
@@ -1,52 +0,0 @@
1
- module Internals
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
- module Combinations # :nodoc:all
11
-
12
- # Memory Combinations contain specific methods for
13
- # calculating score and ids in memory.
14
- #
15
- class Memory < Base
16
-
17
- # Returns the result ids for the allocation.
18
- #
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.
26
- #
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.
29
- #
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
-
46
- end
47
-
48
- end
49
-
50
- end
51
-
52
- end
@@ -1,90 +0,0 @@
1
- module Internals
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
- module Combinations # :nodoc:all
11
-
12
- # Redis Combinations contain specific methods for
13
- # calculating score and ids in memory.
14
- #
15
- class Redis < Base
16
-
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
-
25
- attr_reader :redis
26
-
27
- #
28
- #
29
- def initialize combinations
30
- super combinations
31
-
32
- @redis = self.class.redis
33
- end
34
-
35
- # Returns the result ids for the allocation.
36
- #
37
- def ids amount, offset
38
- return [] if @combinations.empty?
39
-
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
49
-
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.
64
- #
65
- # Note: Generated when this class loads.
66
- #
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
83
-
84
- end
85
-
86
- end
87
-
88
- end
89
-
90
- end
@@ -1,199 +0,0 @@
1
- module Internals
2
-
3
- module Query
4
-
5
- # The query indexes class bundles indexes given to a query.
6
- #
7
- # Example:
8
- # # If you call
9
- # Search.new dvd_index, mp3_index, video_index
10
- #
11
- # # What it does is take the three given (API-) indexes and
12
- # # bundle them in an index bundle.
13
- #
14
- class Indexes
15
-
16
- attr_reader :indexes
17
-
18
- # Creates a new Query::Indexes.
19
- #
20
- # Its job is to generate all possible combinations.
21
- # Note: We cannot mix memory and redis indexes just yet.
22
- #
23
- def initialize *index_definitions, combinations_type
24
- @combinations_type = combinations_type
25
- @indexes = index_definitions.map(&:internal_indexed)
26
- end
27
-
28
- # Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
29
- #
30
- def prepared_allocations_for tokens, weights = {}
31
- allocations = allocations_for tokens
32
-
33
- # Remove double allocations.
34
- #
35
- allocations.uniq
36
-
37
- # Score the allocations using weights as bias.
38
- #
39
- allocations.calculate_score weights
40
-
41
- # Sort the allocations.
42
- # (allocations are sorted according to score, highest to lowest)
43
- #
44
- allocations.sort!
45
-
46
- # Reduce the amount of allocations.
47
- #
48
- # allocations.reduce_to some_amount
49
-
50
- # Remove identifiers from allocations.
51
- #
52
- # allocations.remove some_array_of_identifiers_to_remove
53
-
54
- allocations
55
- end
56
- # Returns a number of possible allocations for the given tokens.
57
- #
58
- def allocations_for tokens
59
- Allocations.new allocations_ary_for(tokens)
60
- end
61
- def allocations_ary_for tokens
62
- indexes.inject([]) do |allocations, index|
63
- allocations + allocation_for(tokens, index)
64
- end
65
- end
66
- def allocation_for tokens, index
67
- # Expand the combinations.
68
- #
69
- possible_combinations = tokens.possible_combinations_in index
70
-
71
- # Generate all possible combinations.
72
- #
73
- expanded_combinations = expand_combinations_from possible_combinations
74
-
75
- # Add the wrapped possible allocations to the ones we already have.
76
- #
77
- expanded_combinations.map! do |expanded_combination|
78
- Allocation.new @combinations_type.new(expanded_combination), index.result_identifier # TODO Do not extract result_identifier.
79
- end
80
- end
81
-
82
- # This is the core of the search engine. No kidding.
83
- #
84
- # Gets an array of
85
- # [
86
- # [<combinations for token1>],
87
- # [<combinations for token2>],
88
- # [<combinations for token3>]
89
- # ]
90
- #
91
- # Generates all possible allocations of combinations.
92
- # [
93
- # [first combination of token1, first c of t2, first c of t3],
94
- # [first combination of token1, first c of t2, second c of t3]
95
- # ...
96
- # ]
97
- #
98
- # Generates all possible combinations of array elements:
99
- # [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]]
100
- # Note: Also calculates the weights and sorts them accordingly.
101
- #
102
- # Note: This is a heavily optimized ruby version.
103
- #
104
- # Works like this:
105
- # [1,2,3], [a,b,c], [k,l,m] are expanded to
106
- # group mult: 1
107
- # <- single mult ->
108
- # [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
109
- # group mult: 3
110
- # <- -> s/m
111
- # [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
112
- # group mult: 9
113
- # <> s/m
114
- # [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
115
- #
116
- # It is then recombined, where
117
- # [
118
- # [a,a,b,b,c,c]
119
- # [d,e,d,e,d,e]
120
- # ]
121
- # becomes
122
- # [
123
- # [a,d],
124
- # [a,e],
125
- # [b,d],
126
- # [b,e],
127
- # [c,d],
128
- # [c,e]
129
- # ]
130
- #
131
- # Note: Not using transpose as it is slower.
132
- #
133
- # Returns nil if there are no combinations.
134
- #
135
- # Note: Of course I could split this method up into smaller
136
- # ones, but I guess I am a bit sentimental.
137
- #
138
- def expand_combinations_from possible_combinations
139
- # If an element has size 0, this means one of the
140
- # tokens could not be allocated.
141
- #
142
- return [] if possible_combinations.any?(&:empty?)
143
-
144
- # Generate the first multiplicator "with which" (well, not quite) to multiply the smallest amount of combinations.
145
- #
146
- single_mult = possible_combinations.inject(1) { |total, combinations| total * combinations.size }
147
-
148
- # Initialize a group multiplicator.
149
- #
150
- group_mult = 1
151
-
152
- # The expanding part to line up the combinations
153
- # for later combination in allocations.
154
- #
155
- possible_combinations.collect! do |combinations|
156
-
157
- # Get the size of the combinations of the first token.
158
- #
159
- combinations_size = combinations.size
160
-
161
- # Special case: If there is no combination for one of the tokens.
162
- # In that case, we just use the same single mult for
163
- # the next iteration.
164
- # If there are combinations, we divide the single mult
165
- # by the number of combinations.
166
- #
167
- single_mult /= combinations_size unless combinations_size.zero?
168
-
169
- # Expand each combination by the single mult:
170
- # [a,b,c]
171
- # [a,a,a, b,b,b, c,c,c]
172
- # Then, expand the result by the group mult:
173
- # [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]
174
- #
175
- combinations = combinations.inject([]) do |total, combination|
176
- total + Array.new(single_mult, combination)
177
- end * group_mult
178
-
179
- # Multiply the group mult by the combinations size,
180
- # since the next combinations' single mult is smaller
181
- # and we need to adjust for that.
182
- #
183
- group_mult = group_mult * combinations_size
184
-
185
- # Return the combinations.
186
- #
187
- combinations
188
- end
189
-
190
- return [] if possible_combinations.empty?
191
-
192
- possible_combinations.shift.zip *possible_combinations
193
- end
194
-
195
- end
196
-
197
- end
198
-
199
- end
@@ -1,82 +0,0 @@
1
- # coding: utf-8
2
- #
3
- module Internals
4
-
5
- #
6
- #
7
- module Query
8
-
9
- # A single qualifier.
10
- #
11
- class Qualifier # :nodoc:all
12
-
13
- attr_reader :normalized_qualifier, :codes
14
-
15
- #
16
- #
17
- # codes is an array.
18
- #
19
- def initialize normalized_qualifier, codes
20
- @normalized_qualifier = normalized_qualifier
21
- @codes = codes.map &:to_sym
22
- end
23
-
24
- # Will overwrite if the key is present in the hash.
25
- #
26
- def inject_into hash
27
- codes.each do |code|
28
- hash[code] = normalized_qualifier
29
- end
30
- end
31
-
32
- end
33
-
34
- # Collection class for qualifiers.
35
- #
36
- class Qualifiers # :nodoc:all
37
-
38
- attr_reader :qualifiers, :normalization_mapping
39
-
40
- delegate :<<, :to => :qualifiers
41
-
42
- #
43
- #
44
- def initialize
45
- @qualifiers = []
46
- @normalization_mapping = {}
47
- end
48
- def self.instance
49
- @instanec ||= new
50
- end
51
-
52
- # TODO Spec.
53
- #
54
- def self.add name, qualifiers
55
- instance << Qualifier.new(name, qualifiers)
56
- end
57
-
58
- # Uses the qualifiers to prepare (optimize) the qualifier handling.
59
- #
60
- def prepare
61
- qualifiers.each do |qualifier|
62
- qualifier.inject_into normalization_mapping
63
- end
64
- end
65
-
66
- # Normalizes the given qualifier.
67
- #
68
- # Returns nil if it is not allowed, the normalized qualifier if it is.
69
- #
70
- # Note: Normalizes.
71
- #
72
- def normalize qualifier
73
- return nil if qualifier.blank?
74
-
75
- normalization_mapping[qualifier.to_sym]
76
- end
77
-
78
- end
79
-
80
- end
81
-
82
- end
@@ -1,202 +0,0 @@
1
- module Internals
2
-
3
- module Query
4
-
5
- # This is a query token. Together with other tokens it makes up a query.
6
- #
7
- # It remembers the original form, and and a normalized form.
8
- #
9
- # It also knows whether it needs to look for similarity (bla~), or whether it is a partial (bla*).
10
- #
11
- class Token # :nodoc:all
12
-
13
- attr_reader :text, :original
14
- attr_writer :similar
15
-
16
- delegate :blank?, :to => :text
17
-
18
- # Normal initializer.
19
- #
20
- # Note: Use this if you do not want a qualified and normalized token.
21
- #
22
- def initialize text
23
- @text = text
24
- end
25
-
26
- # Returns a qualified and normalized token.
27
- #
28
- # Note: Use this in the search engine if you need a qualified
29
- # and normalized token. I.e. one prepared for a search.
30
- #
31
- def self.processed text, downcase = true
32
- new(text).process downcase
33
- end
34
- def process downcases = true
35
- qualify
36
- extract_original
37
- downcase if downcases
38
- partialize
39
- similarize
40
- remove_illegals
41
- symbolize
42
- self
43
- end
44
-
45
- # This returns an array of predefined category names if the user has given any.
46
- #
47
- def user_defined_category_names
48
- @qualifiers
49
- end
50
-
51
- # Extracts a qualifier for this token and pre-assigns an allocation.
52
- #
53
- # Note: Removes the qualifier if it is not allowed.
54
- #
55
- def qualify
56
- @qualifiers, @text = split @text
57
- @qualifiers && @qualifiers.collect! { |qualifier| Query::Qualifiers.instance.normalize qualifier }.compact!
58
- @qualifiers
59
- end
60
- def extract_original
61
- @original = @text.dup
62
- end
63
-
64
- # Downcases the text.
65
- #
66
- def downcase
67
- @text.downcase!
68
- end
69
-
70
- # Partial is a conditional setter.
71
- #
72
- # It is only settable if it hasn't been set yet.
73
- #
74
- def partial= partial
75
- @partial = partial if @partial.nil?
76
- end
77
- def partial?
78
- !@similar && @partial
79
- end
80
-
81
- # If the text ends with *, partialize it. If with ", don't.
82
- #
83
- # The latter wins. So "hello*" will not be partially searched.
84
- #
85
- @@no_partial = /\"\Z/
86
- @@partial = /\*\Z/
87
- def partialize
88
- self.partial = false and return unless @text !~ @@no_partial
89
- self.partial = true unless @text !~ @@partial
90
- end
91
-
92
- # If the text ends with ~ similarize it. If with ", don't.
93
- #
94
- # The latter wins.
95
- #
96
- @@no_similar = /\"\Z/
97
- @@similar = /\~\Z/
98
- def similarize
99
- self.similar = false and return if @text =~ @@no_similar
100
- self.similar = true if @text =~ @@similar
101
- end
102
-
103
- def similar?
104
- @similar
105
- end
106
-
107
- # Normalizes this token's text.
108
- #
109
- @@illegals = /["*~]/
110
- def remove_illegals
111
- @text.gsub! @@illegals, '' unless @text.blank?
112
- end
113
-
114
- #
115
- #
116
- def symbolize
117
- @text = @text.to_sym
118
- end
119
-
120
- # Returns an array of possible combinations.
121
- #
122
- def possible_combinations_in index
123
- index.possible_combinations self
124
- end
125
-
126
- # Returns a token with the next similar text.
127
- #
128
- # TODO Rewrite this. It is hard to understand. Also spec performance.
129
- #
130
- def next_similar_token category
131
- token = self.dup
132
- token if token.next_similar category.bundle_for(token)
133
- end
134
- # Sets and returns the next similar word.
135
- #
136
- # Note: Also overrides the original.
137
- #
138
- def next_similar bundle
139
- @text = @original = (similarity(bundle).shift || return) if similar?
140
- end
141
- # Lazy similar reader.
142
- #
143
- def similarity bundle = nil
144
- @similarity || @similarity = generate_similarity_for(bundle)
145
- end
146
- # Returns an enumerator that traverses over the similar.
147
- #
148
- # Note: The dup isn't too nice – since it is needed on account of the shift, above.
149
- # (We avoid a StopIteration exception. Which of both is less evil?)
150
- #
151
- def generate_similarity_for bundle
152
- bundle.similar(@text).dup || []
153
- end
154
-
155
- #
156
- #
157
- def to_result
158
- [@original, @text]
159
- end
160
-
161
- # Internal identifier.
162
- #
163
- def identifier
164
- "#{similar?? :similarity : :index}:#{@text}"
165
- end
166
-
167
- # If the originals & the text are the same, they are the same.
168
- #
169
- def == other
170
- self.original == other.original && self.text == other.text
171
- end
172
-
173
- # Displays the qualifier text and the text, joined.
174
- #
175
- # e.g. name:meier
176
- #
177
- @@split_qualifier_text = ':'
178
- @@split_qualifiers = ','
179
- def to_s
180
- [@qualifiers && @qualifiers.join(@@split_qualifiers), @text].compact.join @@split_qualifier_text
181
- end
182
-
183
- private
184
-
185
- # Splits text into a qualifier and text.
186
- #
187
- # Returns [qualifier, text].
188
- #
189
- def split unqualified_text
190
- qualifiers, text = (unqualified_text || '').split(@@split_qualifier_text, 2)
191
- if text.blank?
192
- [nil, (qualifiers || '')]
193
- else
194
- [qualifiers.split(@@split_qualifiers), text]
195
- end
196
- end
197
-
198
- end
199
-
200
- end
201
-
202
- end