picky 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (229) hide show
  1. data/lib/picky/{alias_instances.rb → aliases.rb} +1 -3
  2. data/lib/picky/application.rb +18 -19
  3. data/lib/picky/cores.rb +1 -1
  4. data/lib/picky/generators/aliases.rb +3 -0
  5. data/lib/picky/index/base.rb +179 -0
  6. data/lib/picky/index/memory.rb +28 -0
  7. data/lib/picky/index/redis.rb +28 -0
  8. data/lib/picky/{indexes_api.rb → index_bundle.rb} +16 -16
  9. data/lib/picky/indexed/indexes.rb +11 -7
  10. data/lib/picky/indexing/indexes.rb +14 -8
  11. data/lib/picky/internals/adapters/rack/base.rb +27 -0
  12. data/lib/picky/internals/adapters/rack/live_parameters.rb +37 -0
  13. data/lib/picky/internals/adapters/rack/query.rb +63 -0
  14. data/lib/picky/internals/adapters/rack.rb +34 -0
  15. data/lib/picky/{calculations → internals/calculations}/location.rb +0 -0
  16. data/lib/picky/{cli.rb → internals/cli.rb} +0 -0
  17. data/lib/picky/{configuration → internals/configuration}/index.rb +8 -2
  18. data/lib/picky/{ext → internals/ext}/maybe_compile.rb +0 -0
  19. data/lib/picky/{ext → internals/ext}/ruby19/extconf.rb +0 -0
  20. data/lib/picky/{ext → internals/ext}/ruby19/performant.c +0 -0
  21. data/lib/picky/{extensions → internals/extensions}/array.rb +0 -0
  22. data/lib/picky/{extensions → internals/extensions}/hash.rb +0 -0
  23. data/lib/picky/{extensions → internals/extensions}/module.rb +0 -0
  24. data/lib/picky/{extensions → internals/extensions}/object.rb +0 -0
  25. data/lib/picky/{extensions → internals/extensions}/symbol.rb +0 -0
  26. data/lib/picky/internals/frontend_adapters/rack.rb +154 -0
  27. data/lib/picky/internals/generators/base.rb +19 -0
  28. data/lib/picky/internals/generators/partial/default.rb +7 -0
  29. data/lib/picky/internals/generators/partial/none.rb +35 -0
  30. data/lib/picky/internals/generators/partial/strategy.rb +29 -0
  31. data/lib/picky/internals/generators/partial/substring.rb +122 -0
  32. data/lib/picky/internals/generators/partial_generator.rb +19 -0
  33. data/lib/picky/internals/generators/similarity/default.rb +9 -0
  34. data/lib/picky/internals/generators/similarity/double_levenshtone.rb +81 -0
  35. data/lib/picky/internals/generators/similarity/none.rb +35 -0
  36. data/lib/picky/internals/generators/similarity/strategy.rb +11 -0
  37. data/lib/picky/internals/generators/similarity_generator.rb +19 -0
  38. data/lib/picky/internals/generators/strategy.rb +18 -0
  39. data/lib/picky/internals/generators/weights/default.rb +9 -0
  40. data/lib/picky/internals/generators/weights/logarithmic.rb +43 -0
  41. data/lib/picky/internals/generators/weights/strategy.rb +11 -0
  42. data/lib/picky/internals/generators/weights_generator.rb +19 -0
  43. data/lib/picky/{helpers → internals/helpers}/measuring.rb +0 -0
  44. data/lib/picky/internals/index/backend.rb +113 -0
  45. data/lib/picky/internals/index/file/basic.rb +101 -0
  46. data/lib/picky/internals/index/file/json.rb +38 -0
  47. data/lib/picky/internals/index/file/marshal.rb +38 -0
  48. data/lib/picky/internals/index/file/text.rb +60 -0
  49. data/lib/picky/internals/index/files.rb +24 -0
  50. data/lib/picky/internals/index/redis/basic.rb +77 -0
  51. data/lib/picky/internals/index/redis/list_hash.rb +46 -0
  52. data/lib/picky/internals/index/redis/string_hash.rb +35 -0
  53. data/lib/picky/internals/index/redis.rb +44 -0
  54. data/lib/picky/internals/indexed/bundle/base.rb +72 -0
  55. data/lib/picky/internals/indexed/bundle/memory.rb +69 -0
  56. data/lib/picky/internals/indexed/bundle/redis.rb +70 -0
  57. data/lib/picky/internals/indexed/categories.rb +135 -0
  58. data/lib/picky/internals/indexed/category.rb +90 -0
  59. data/lib/picky/internals/indexed/index.rb +57 -0
  60. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/calculation.rb +0 -0
  61. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/location.rb +4 -2
  62. data/lib/picky/{indexed → internals/indexed}/wrappers/bundle/wrapper.rb +1 -1
  63. data/lib/picky/internals/indexed/wrappers/exact_first.rb +65 -0
  64. data/lib/picky/{indexers → internals/indexers}/no_source_specified_error.rb +0 -0
  65. data/lib/picky/{indexers → internals/indexers}/serial.rb +2 -2
  66. data/lib/picky/{indexers → internals/indexers}/solr.rb +0 -0
  67. data/lib/picky/internals/indexing/bundle/base.rb +219 -0
  68. data/lib/picky/internals/indexing/bundle/memory.rb +25 -0
  69. data/lib/picky/internals/indexing/bundle/redis.rb +28 -0
  70. data/lib/picky/internals/indexing/bundle/super_base.rb +65 -0
  71. data/lib/picky/internals/indexing/categories.rb +42 -0
  72. data/lib/picky/internals/indexing/category.rb +120 -0
  73. data/lib/picky/internals/indexing/index.rb +67 -0
  74. data/lib/picky/{performant.rb → internals/performant.rb} +0 -0
  75. data/lib/picky/internals/query/allocation.rb +88 -0
  76. data/lib/picky/internals/query/allocations.rb +137 -0
  77. data/lib/picky/internals/query/combination.rb +80 -0
  78. data/lib/picky/internals/query/combinations/base.rb +84 -0
  79. data/lib/picky/internals/query/combinations/memory.rb +58 -0
  80. data/lib/picky/internals/query/combinations/redis.rb +59 -0
  81. data/lib/picky/internals/query/indexes.rb +180 -0
  82. data/lib/picky/internals/query/qualifiers.rb +81 -0
  83. data/lib/picky/internals/query/token.rb +215 -0
  84. data/lib/picky/internals/query/tokens.rb +89 -0
  85. data/lib/picky/{query → internals/query}/weights.rb +0 -0
  86. data/lib/picky/internals/results/base.rb +106 -0
  87. data/lib/picky/internals/results/full.rb +17 -0
  88. data/lib/picky/internals/results/live.rb +17 -0
  89. data/lib/picky/{solr → internals/solr}/schema_generator.rb +0 -0
  90. data/lib/picky/internals/tokenizers/base.rb +166 -0
  91. data/lib/picky/internals/tokenizers/index.rb +63 -0
  92. data/lib/picky/internals/tokenizers/query.rb +79 -0
  93. data/lib/picky/loader.rb +148 -112
  94. data/lib/picky/query/base.rb +57 -26
  95. data/lib/picky/query/full.rb +1 -1
  96. data/lib/picky/query/live.rb +1 -1
  97. data/lib/picky/sources/db.rb +27 -6
  98. data/lib/tasks/index.rake +3 -3
  99. data/lib/tasks/try.rake +2 -2
  100. data/spec/lib/aliases_spec.rb +9 -0
  101. data/spec/lib/application_spec.rb +3 -3
  102. data/spec/lib/generators/aliases_spec.rb +1 -0
  103. data/spec/lib/{index_api_spec.rb → index/base_spec.rb} +7 -7
  104. data/spec/lib/index_bundle_spec.rb +71 -0
  105. data/spec/lib/indexed/indexes_spec.rb +61 -0
  106. data/spec/lib/indexing/indexes_spec.rb +94 -24
  107. data/spec/lib/{adapters → internals/adapters}/rack/base_spec.rb +2 -2
  108. data/spec/lib/{adapters → internals/adapters}/rack/live_parameters_spec.rb +2 -2
  109. data/spec/lib/{adapters → internals/adapters}/rack/query_spec.rb +2 -2
  110. data/spec/lib/{calculations → internals/calculations}/location_spec.rb +0 -0
  111. data/spec/lib/{cli_spec.rb → internals/cli_spec.rb} +4 -1
  112. data/spec/lib/{configuration → internals/configuration}/index_spec.rb +1 -1
  113. data/spec/lib/{cores_spec.rb → internals/cores_spec.rb} +0 -0
  114. data/spec/lib/{extensions → internals/extensions}/array_spec.rb +0 -0
  115. data/spec/lib/{extensions → internals/extensions}/hash_spec.rb +0 -0
  116. data/spec/lib/{extensions → internals/extensions}/module_spec.rb +0 -0
  117. data/spec/lib/{extensions → internals/extensions}/object_spec.rb +0 -0
  118. data/spec/lib/{extensions → internals/extensions}/symbol_spec.rb +0 -0
  119. data/spec/lib/{frontend_adapters → internals/frontend_adapters}/rack_spec.rb +11 -11
  120. data/spec/lib/{cacher → internals/generators}/cacher_strategy_spec.rb +2 -2
  121. data/spec/lib/internals/generators/partial/default_spec.rb +17 -0
  122. data/spec/lib/internals/generators/partial/none_spec.rb +17 -0
  123. data/spec/lib/{cacher → internals/generators}/partial/substring_spec.rb +26 -27
  124. data/spec/lib/{cacher → internals/generators}/partial_generator_spec.rb +5 -5
  125. data/spec/lib/{cacher → internals/generators}/similarity/double_levenshtone_spec.rb +4 -4
  126. data/spec/lib/{cacher → internals/generators}/similarity/none_spec.rb +2 -2
  127. data/spec/lib/{cacher → internals/generators}/similarity_generator_spec.rb +4 -4
  128. data/spec/lib/{cacher → internals/generators}/weights/logarithmic_spec.rb +2 -2
  129. data/spec/lib/internals/generators/weights_generator_spec.rb +21 -0
  130. data/spec/lib/{helpers → internals/helpers}/measuring_spec.rb +0 -0
  131. data/spec/lib/{index → internals/index}/file/basic_spec.rb +2 -2
  132. data/spec/lib/{index → internals/index}/file/json_spec.rb +2 -2
  133. data/spec/lib/{index → internals/index}/file/marshal_spec.rb +2 -2
  134. data/spec/lib/{index → internals/index}/file/text_spec.rb +2 -2
  135. data/spec/lib/{index → internals/index}/files_spec.rb +2 -2
  136. data/spec/lib/{indexed/bundle_spec.rb → internals/indexed/bundle/memory_spec.rb} +4 -5
  137. data/spec/lib/{indexed → internals/indexed}/categories_spec.rb +13 -13
  138. data/spec/lib/{indexed → internals/indexed}/category_spec.rb +59 -32
  139. data/spec/lib/{indexed → internals/indexed}/index_spec.rb +5 -5
  140. data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/calculation_spec.rb +0 -0
  141. data/spec/lib/{indexed → internals/indexed}/wrappers/bundle/wrapper_spec.rb +0 -0
  142. data/spec/lib/{indexed → internals/indexed}/wrappers/exact_first_spec.rb +5 -5
  143. data/spec/lib/{indexers → internals/indexers}/serial_spec.rb +0 -0
  144. data/spec/lib/{indexing/bundle_partial_generation_speed_spec.rb → internals/indexing/bundle/memory_partial_generation_speed_spec.rb} +3 -3
  145. data/spec/lib/{indexing/bundle_spec.rb → internals/indexing/bundle/memory_spec.rb} +3 -3
  146. data/spec/lib/{index/bundle_spec.rb → internals/indexing/bundle/super_base_spec.rb} +9 -3
  147. data/spec/lib/{indexing → internals/indexing}/category_spec.rb +3 -3
  148. data/spec/lib/{indexing → internals/indexing}/index_spec.rb +3 -3
  149. data/spec/lib/internals/indexing/indexes_spec.rb +36 -0
  150. data/spec/lib/{interfaces → internals/interfaces}/live_parameters_spec.rb +0 -0
  151. data/spec/lib/internals/results/base_spec.rb +105 -0
  152. data/spec/lib/internals/results/full_spec.rb +78 -0
  153. data/spec/lib/internals/results/live_spec.rb +88 -0
  154. data/spec/lib/{solr → internals/solr}/schema_generator_spec.rb +0 -0
  155. data/spec/lib/{tokenizers → internals/tokenizers}/base_spec.rb +3 -3
  156. data/spec/lib/{tokenizers → internals/tokenizers}/index_spec.rb +9 -9
  157. data/spec/lib/{tokenizers → internals/tokenizers}/query_spec.rb +11 -11
  158. data/spec/lib/query/allocation_spec.rb +12 -12
  159. data/spec/lib/query/allocations_spec.rb +19 -19
  160. data/spec/lib/query/base_spec.rb +28 -4
  161. data/spec/lib/query/combination_spec.rb +8 -9
  162. data/spec/lib/query/combinations/base_spec.rb +116 -0
  163. data/spec/lib/query/{combinations_spec.rb → combinations/memory_spec.rb} +14 -14
  164. data/spec/lib/query/combinations/redis_spec.rb +132 -0
  165. data/spec/lib/query/full_spec.rb +2 -2
  166. data/spec/lib/query/indexes_spec.rb +81 -0
  167. data/spec/lib/query/live_spec.rb +3 -3
  168. data/spec/lib/query/qualifiers_spec.rb +6 -6
  169. data/spec/lib/query/token_spec.rb +38 -38
  170. data/spec/lib/query/tokens_spec.rb +35 -35
  171. data/spec/lib/sources/db_spec.rb +23 -18
  172. metadata +212 -181
  173. data/lib/picky/adapters/rack/base.rb +0 -23
  174. data/lib/picky/adapters/rack/live_parameters.rb +0 -33
  175. data/lib/picky/adapters/rack/query.rb +0 -59
  176. data/lib/picky/adapters/rack.rb +0 -28
  177. data/lib/picky/cacher/convenience.rb +0 -3
  178. data/lib/picky/cacher/generator.rb +0 -15
  179. data/lib/picky/cacher/partial/default.rb +0 -5
  180. data/lib/picky/cacher/partial/none.rb +0 -31
  181. data/lib/picky/cacher/partial/strategy.rb +0 -21
  182. data/lib/picky/cacher/partial/substring.rb +0 -118
  183. data/lib/picky/cacher/partial_generator.rb +0 -15
  184. data/lib/picky/cacher/similarity/default.rb +0 -7
  185. data/lib/picky/cacher/similarity/double_levenshtone.rb +0 -77
  186. data/lib/picky/cacher/similarity/none.rb +0 -31
  187. data/lib/picky/cacher/similarity/strategy.rb +0 -9
  188. data/lib/picky/cacher/similarity_generator.rb +0 -15
  189. data/lib/picky/cacher/strategy.rb +0 -12
  190. data/lib/picky/cacher/weights/default.rb +0 -7
  191. data/lib/picky/cacher/weights/logarithmic.rb +0 -39
  192. data/lib/picky/cacher/weights/strategy.rb +0 -9
  193. data/lib/picky/cacher/weights_generator.rb +0 -15
  194. data/lib/picky/frontend_adapters/rack.rb +0 -150
  195. data/lib/picky/index/bundle.rb +0 -54
  196. data/lib/picky/index/file/basic.rb +0 -97
  197. data/lib/picky/index/file/json.rb +0 -34
  198. data/lib/picky/index/file/marshal.rb +0 -34
  199. data/lib/picky/index/file/text.rb +0 -56
  200. data/lib/picky/index/files.rb +0 -118
  201. data/lib/picky/index_api.rb +0 -175
  202. data/lib/picky/indexed/bundle.rb +0 -54
  203. data/lib/picky/indexed/categories.rb +0 -131
  204. data/lib/picky/indexed/category.rb +0 -85
  205. data/lib/picky/indexed/index.rb +0 -39
  206. data/lib/picky/indexed/wrappers/exact_first.rb +0 -61
  207. data/lib/picky/indexing/bundle.rb +0 -213
  208. data/lib/picky/indexing/categories.rb +0 -38
  209. data/lib/picky/indexing/category.rb +0 -117
  210. data/lib/picky/indexing/index.rb +0 -55
  211. data/lib/picky/query/allocation.rb +0 -82
  212. data/lib/picky/query/allocations.rb +0 -130
  213. data/lib/picky/query/combination.rb +0 -74
  214. data/lib/picky/query/combinations.rb +0 -105
  215. data/lib/picky/query/qualifiers.rb +0 -77
  216. data/lib/picky/query/token.rb +0 -202
  217. data/lib/picky/query/tokens.rb +0 -86
  218. data/lib/picky/query/weigher.rb +0 -165
  219. data/lib/picky/results/base.rb +0 -102
  220. data/lib/picky/results/full.rb +0 -13
  221. data/lib/picky/results/live.rb +0 -13
  222. data/lib/picky/tokenizers/base.rb +0 -161
  223. data/lib/picky/tokenizers/index.rb +0 -58
  224. data/lib/picky/tokenizers/query.rb +0 -74
  225. data/spec/lib/cacher/partial/default_spec.rb +0 -15
  226. data/spec/lib/cacher/partial/none_spec.rb +0 -17
  227. data/spec/lib/cacher/weights_generator_spec.rb +0 -21
  228. data/spec/lib/results/base_spec.rb +0 -257
  229. data/spec/lib/results/live_spec.rb +0 -15
@@ -0,0 +1,72 @@
1
+ module Internals
2
+
3
+ module Indexed # :nodoc:all
4
+
5
+ # TODO Rewrite.
6
+ #
7
+ # A Bundle is a number of indexes
8
+ # per [index, category] combination.
9
+ #
10
+ # At most, there are three indexes:
11
+ # * *core* index (always used)
12
+ # * *weights* index (always used)
13
+ # * *similarity* index (used with similarity)
14
+ #
15
+ # In Picky, indexing is separated from the index
16
+ # handling itself through a parallel structure.
17
+ #
18
+ # Both use methods provided by this base class, but
19
+ # have very different goals:
20
+ #
21
+ # * *Indexing*::*Bundle* is just concerned with creating index files
22
+ # and providing helper functions to e.g. check the indexes.
23
+ #
24
+ # * *Index*::*Bundle* is concerned with loading these index files into
25
+ # memory and looking up search data as fast as possible.
26
+ #
27
+ module Bundle
28
+
29
+ class Base
30
+
31
+ attr_reader :identifier, :configuration
32
+ attr_accessor :similarity_strategy
33
+
34
+ delegate :[], :to => :configuration
35
+
36
+ def initialize name, configuration, similarity_strategy
37
+ @identifier = "#{configuration.identifier}:#{name}"
38
+
39
+ @index = {}
40
+ @weights = {}
41
+ @similarity = {}
42
+
43
+ @similarity_strategy = similarity_strategy
44
+ end
45
+
46
+ # Get a list of similar texts.
47
+ #
48
+ # Note: Does not return itself.
49
+ #
50
+ def similar text
51
+ code = similarity_strategy.encoded text
52
+ similar_codes = code && @similarity[code]
53
+ similar_codes.delete text if similar_codes
54
+ similar_codes || []
55
+ end
56
+
57
+ # Loads all indexes.
58
+ #
59
+ def load
60
+ load_index
61
+ load_weights
62
+ load_similarity
63
+ load_configuration
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,69 @@
1
+ module Internals
2
+
3
+ # encoding: utf-8
4
+ #
5
+ module Indexed # :nodoc:all
6
+
7
+ #
8
+ #
9
+ module Bundle
10
+
11
+ # This is the _actual_ index (based on memory).
12
+ #
13
+ # Handles exact/partial index, weights index, and similarity index.
14
+ #
15
+ # Delegates file handling and checking to an *Indexed*::*Files* object.
16
+ #
17
+ class Memory < Base
18
+
19
+ attr_accessor :index, :weights, :similarity, :configuration
20
+
21
+ delegate :[], :to => :configuration
22
+
23
+ def initialize name, configuration, *args
24
+ super name, configuration, *args
25
+
26
+ @configuration = {} # A hash with config options.
27
+
28
+ @backend = Internals::Index::Files.new name, configuration
29
+ end
30
+
31
+ # Get the ids for the given symbol.
32
+ #
33
+ def ids sym
34
+ @index[sym] || []
35
+ end
36
+ # Get a weight for the given symbol.
37
+ #
38
+ def weight sym
39
+ @weights[sym]
40
+ end
41
+
42
+ # Loads the core index.
43
+ #
44
+ def load_index
45
+ self.index = @backend.load_index
46
+ end
47
+ # Loads the weights index.
48
+ #
49
+ def load_weights
50
+ self.weights = @backend.load_weights
51
+ end
52
+ # Loads the similarity index.
53
+ #
54
+ def load_similarity
55
+ self.similarity = @backend.load_similarity
56
+ end
57
+ # Loads the configuration.
58
+ #
59
+ def load_configuration
60
+ self.configuration = @backend.load_configuration
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,70 @@
1
+ module Internals
2
+
3
+ # encoding: utf-8
4
+ #
5
+ module Indexed # :nodoc:all
6
+
7
+ #
8
+ #
9
+ module Bundle
10
+
11
+ # This is the _actual_ index (based on Redis).
12
+ #
13
+ # Handles exact/partial index, weights index, and similarity index.
14
+ #
15
+ class Redis < Base
16
+
17
+ def initialize name, configuration, *args
18
+ super name, configuration, *args
19
+
20
+ @backend = Internals::Index::Redis.new name, configuration
21
+ end
22
+
23
+ # Get the ids for the given symbol.
24
+ #
25
+ # Ids are an array of string values in Redis.
26
+ #
27
+ def ids sym
28
+ @backend.ids sym
29
+ end
30
+ # Get a weight for the given symbol.
31
+ #
32
+ # A weight is a string value in Redis. TODO Convert?
33
+ #
34
+ def weight sym
35
+ @backend.weight sym
36
+ end
37
+ # TODO Spec. Doc.
38
+ #
39
+ def [] sym
40
+ @backend.setting sym
41
+ end
42
+
43
+ # Loads the core index.
44
+ #
45
+ def load_index
46
+ # TODO check if it is there.
47
+ end
48
+ # Loads the weights index.
49
+ #
50
+ def load_weights
51
+ # TODO check if it is there.
52
+ end
53
+ # Loads the similarity index.
54
+ #
55
+ def load_similarity
56
+ # TODO check if it is there.
57
+ end
58
+ # Loads the configuration.
59
+ #
60
+ def load_configuration
61
+ # TODO check if it is there.
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,135 @@
1
+ module Internals
2
+
3
+ module Indexed
4
+
5
+ class Categories
6
+
7
+ attr_reader :categories, :category_hash, :ignore_unassigned_tokens
8
+
9
+ each_delegate :load_from_cache,
10
+ :to => :categories
11
+
12
+ # A list of indexed categories.
13
+ #
14
+ # Options:
15
+ # * ignore_unassigned_tokens: Ignore the given token if it cannot be matched to a category.
16
+ # The default behaviour is that if a token does not match to
17
+ # any category, the query will not return anything (since a
18
+ # single token cannot be matched). If you set this option to
19
+ # true, any token that cannot be matched to a category will be
20
+ # simply ignored.
21
+ # Use this if only a few matched words are important, like for
22
+ # example of the query "Jonathan Myers 86455 Las Cucarachas"
23
+ # you only want to match the zipcode, to have the search engine
24
+ # display advertisements on the side for the zipcode.
25
+ # Nifty! :)
26
+ #
27
+ def initialize options = {}
28
+ clear
29
+
30
+ @ignore_unassigned_tokens = options[:ignore_unassigned_tokens] || false
31
+ end
32
+
33
+ # Clears both the array of categories and the hash of categories.
34
+ #
35
+ def clear
36
+ @categories = []
37
+ @category_hash = {}
38
+ end
39
+
40
+ # Add the given category to the list of categories.
41
+ #
42
+ def << category
43
+ categories << category
44
+ # Note: [category] is an optimization, since I need an array
45
+ # of categories.
46
+ # It's faster to just package it in an array on loading
47
+ # Picky than doing it over and over with each query.
48
+ #
49
+ category_hash[category.name] = [category]
50
+ end
51
+
52
+ # Return all possible combinations for the given token.
53
+ #
54
+ # This checks if it needs to also search through similar
55
+ # tokens, if for example, the token is one with ~.
56
+ # If yes, it puts together all solutions.
57
+ #
58
+ def possible_combinations_for token
59
+ token.similar? ? similar_possible_for(token) : possible_for(token)
60
+ end
61
+ # Gets all similar tokens and puts together the possible combinations
62
+ # for each found similar token.
63
+ #
64
+ def similar_possible_for token
65
+ # Get as many similar tokens as necessary
66
+ #
67
+ tokens = similar_tokens_for token
68
+ # possible combinations
69
+ #
70
+ inject_possible_for tokens
71
+ end
72
+ def similar_tokens_for token
73
+ text = token.text
74
+ categories.inject([]) do |result, category|
75
+ next_token = token
76
+ # Note: We could also break off here if not all the available
77
+ # similars are needed.
78
+ # Wait for a concrete case that needs this before taking
79
+ # action.
80
+ #
81
+ while next_token = next_token.next_similar_token(category)
82
+ result << next_token if next_token && next_token.text != text
83
+ end
84
+ result
85
+ end
86
+ end
87
+ def inject_possible_for tokens
88
+ tokens.inject([]) do |result, token|
89
+ possible = possible_categories token
90
+ result + possible_for(token, possible)
91
+ end
92
+ end
93
+
94
+ # Returns possible Combinations for the token.
95
+ #
96
+ # Note: The preselected_categories param is an optimization.
97
+ #
98
+ # Note: Returns [] if no categories matched (will produce no result).
99
+ # Returns nil if this token needs to be removed from the query.
100
+ # (Also none of the categories matched, but the ignore unassigned
101
+ # tokens option is true)
102
+ #
103
+ def possible_for token, preselected_categories = nil
104
+ possible = (preselected_categories || possible_categories(token)).map { |category| category.combination_for(token) }
105
+ possible.compact!
106
+ # This is an optimization to mark tokens that are ignored.
107
+ #
108
+ return if ignore_unassigned_tokens && possible.empty?
109
+ possible # wrap in combinations
110
+ end
111
+ # This returns the possible categories for this token.
112
+ # If the user has already preselected a category for this token,
113
+ # like "artist:moby", if not just return all for the given token,
114
+ # since all are possible.
115
+ #
116
+ # Note: Once I thought this was called too often. But it is not (18.01.2011).
117
+ #
118
+ def possible_categories token
119
+ user_defined_categories(token) || categories
120
+ end
121
+ # This returns the array of categories if the user has defined
122
+ # an existing category.
123
+ #
124
+ # Note: Returns nil if the user did not define one
125
+ # or if he/she has defined a non-existing one.
126
+ #
127
+ def user_defined_categories token
128
+ category_hash[token.user_defined_category_name]
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end
@@ -0,0 +1,90 @@
1
+ module Internals
2
+
3
+ module Indexed
4
+
5
+ # An index category holds a exact and a partial index for a given category.
6
+ #
7
+ # For example an index category for names holds a exact and
8
+ # a partial index bundle for names.
9
+ #
10
+ class Category
11
+
12
+ attr_accessor :exact
13
+ attr_reader :identifier, :name
14
+ attr_writer :partial
15
+
16
+ #
17
+ #
18
+ def initialize name, index, options = {}
19
+ @name = name
20
+
21
+ configuration = Configuration::Index.new index, self
22
+
23
+ @identifier = configuration.identifier
24
+
25
+ # TODO Push the defaults out into the index.
26
+ #
27
+ @partial_strategy = options[:partial] || Internals::Generators::Partial::Default
28
+ similarity = options[:similarity] || Internals::Generators::Similarity::Default
29
+
30
+ bundle_class = options[:indexed_bundle_class] || Bundle::Memory
31
+ @exact = bundle_class.new :exact, configuration, similarity
32
+ @partial = bundle_class.new :partial, configuration, similarity
33
+
34
+ # @exact = exact_lambda.call(@exact, @partial) if exact_lambda = options[:exact_lambda]
35
+ # @partial = partial_lambda.call(@exact, @partial) if partial_lambda = options[:partial_lambda]
36
+
37
+ # TODO Extract?
38
+ #
39
+ Query::Qualifiers.add(configuration.category_name, generate_qualifiers_from(options) || [name])
40
+ end
41
+
42
+ # TODO Move to Index.
43
+ #
44
+ def generate_qualifiers_from options
45
+ options[:qualifiers] || options[:qualifier] && [options[:qualifier]]
46
+ end
47
+
48
+ # Loads the index from cache.
49
+ #
50
+ def load_from_cache
51
+ timed_exclaim "Loading index #{identifier}."
52
+ exact.load
53
+ partial.load
54
+ end
55
+
56
+ # Gets the weight for this token's text.
57
+ #
58
+ def weight token
59
+ bundle_for(token).weight token.text
60
+ end
61
+
62
+ # Gets the ids for this token's text.
63
+ #
64
+ def ids token
65
+ bundle_for(token).ids token.text
66
+ end
67
+
68
+ # Returns the right index bundle for this token.
69
+ #
70
+ def bundle_for token
71
+ token.partial?? partial : exact
72
+ end
73
+
74
+ # The partial strategy defines whether to really use the partial index.
75
+ #
76
+ def partial
77
+ @partial_strategy.use_exact_for_partial?? @exact : @partial
78
+ end
79
+
80
+ #
81
+ #
82
+ def combination_for token
83
+ weight(token) && Internals::Query::Combination.new(token, self)
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,57 @@
1
+ module Internals
2
+
3
+ module Indexed
4
+
5
+ #
6
+ #
7
+ class Index
8
+
9
+ attr_reader :name, :result_identifier, :combinator, :categories
10
+
11
+ delegate :load_from_cache,
12
+ :to => :categories
13
+
14
+ # TODO Externalize?
15
+ #
16
+ def initialize name, options = {}
17
+ @name = name
18
+
19
+ @result_identifier = options[:result_identifier] || name
20
+ @bundle_class = options[:indexed_bundle_class] # TODO This should actually be a fixed parameter.
21
+ ignore_unassigned_tokens = options[:ignore_unassigned_tokens] || false # TODO Move to query, somehow.
22
+
23
+ @categories = Categories.new ignore_unassigned_tokens: ignore_unassigned_tokens
24
+ end
25
+
26
+ # TODO Doc. Externalize?
27
+ #
28
+ def define_category category_name, options = {}
29
+ options = default_category_options.merge options
30
+
31
+ new_category = Category.new category_name, self, options
32
+ categories << new_category
33
+ new_category
34
+ end
35
+
36
+ # By default, the category uses
37
+ # * the index's bundle type.
38
+ #
39
+ def default_category_options
40
+ {
41
+ :indexed_bundle_class => @bundle_class
42
+ }
43
+ end
44
+
45
+ # Return the possible combinations for this token.
46
+ #
47
+ # A combination is a tuple <token, index_bundle>.
48
+ #
49
+ def possible_combinations token
50
+ categories.possible_combinations_for token
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -13,7 +13,7 @@ module Indexed
13
13
  precision = options[:precision] || 1
14
14
  user_grid = options[:grid] || raise("Gridsize needs to be given for location #{bundle.identifier}.")
15
15
 
16
- @calculation = Calculations::Location.new user_grid, precision
16
+ @calculation = Calculations::Location.new user_grid, precision
17
17
  end
18
18
 
19
19
  #
@@ -28,7 +28,9 @@ module Indexed
28
28
  # Load first the bundle, then extract the config.
29
29
  #
30
30
  bundle.load
31
- minimum = bundle[:location_minimum] || raise("Configuration :location_minimum for #{bundle.identifier} missing. Did you run rake index already?")
31
+ # TODO Move the to_f to the backend.
32
+ #
33
+ minimum = bundle[:location_minimum] && bundle[:location_minimum].to_f || raise("Configuration :location_minimum for #{bundle.identifier} missing. Did you run rake index already?")
32
34
  @calculation.minimum = minimum
33
35
  end
34
36
 
@@ -15,7 +15,7 @@ module Indexed
15
15
  @bundle = bundle
16
16
  end
17
17
 
18
- delegate :load, :ids, :weight, :to => :@bundle
18
+ delegate :load, :ids, :weight, :identifier, :to => :@bundle
19
19
 
20
20
  end
21
21
 
@@ -0,0 +1,65 @@
1
+ module Internals
2
+
3
+ # encoding: utf-8
4
+ #
5
+ module Indexed
6
+
7
+ # TODO Spec
8
+ #
9
+ module Wrappers
10
+
11
+ # This index combines an exact and partial index.
12
+ # It serves to order the results such that exact hits are found first.
13
+ #
14
+ # TODO Need to use the right subtokens. Bake in?
15
+ #
16
+ class ExactFirst < Indexed::Bundle::Memory
17
+
18
+ delegate :similar,
19
+ :identifier,
20
+ :name,
21
+ :to => :@exact
22
+ delegate :index,
23
+ :category,
24
+ :weight,
25
+ :generate_partial_from,
26
+ :generate_caches_from_memory,
27
+ :generate_derived,
28
+ :dump,
29
+ :load,
30
+ :to => :@partial
31
+
32
+ def initialize category
33
+ @exact = category.exact
34
+ @partial = category.partial
35
+ end
36
+
37
+ def self.wrap index_or_category
38
+ if index_or_category.respond_to? :categories
39
+ wrap_each_of index_or_category.categories
40
+ index_or_category
41
+ else
42
+ new index_or_category
43
+ end
44
+ end
45
+ # TODO Do not extract categories!
46
+ #
47
+ def self.wrap_each_of categories
48
+ categories.categories.collect! { |category| new(category) }
49
+ end
50
+
51
+ def ids text
52
+ @exact.ids(text) + @partial.ids(text)
53
+ end
54
+
55
+ def weight text
56
+ [@exact.weight(text) || 0, @partial.weight(text) || 0].max
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -17,7 +17,7 @@ module Indexers
17
17
  # Raise a no source exception.
18
18
  #
19
19
  def raise_no_source
20
- raise NoSourceSpecifiedException.new("No source given for #{@configuration.identifier}.")
20
+ raise NoSourceSpecifiedException.new("No source given for #{@configuration}.")
21
21
  end
22
22
 
23
23
  # Delegates the key format to the source.
@@ -65,7 +65,7 @@ module Indexers
65
65
  end
66
66
  end
67
67
  def indexing_message
68
- timed_exclaim "INDEX #{@configuration.identifier}" # TODO from ...
68
+ timed_exclaim "INDEX #{@configuration}" # TODO from ...
69
69
  end
70
70
 
71
71
  end
File without changes