picky 3.0.0.pre1 → 3.0.0.pre2
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.
- data/lib/picky/adapters/rack/search.rb +3 -3
- data/lib/picky/adapters/rack.rb +3 -3
- data/lib/picky/application.rb +5 -3
- data/lib/picky/backend/file/json.rb +7 -0
- data/lib/picky/backend/file/text.rb +2 -2
- data/lib/picky/character_substituters/west_european.rb +3 -0
- data/lib/picky/extensions/symbol.rb +4 -4
- data/lib/picky/indexes/index.rb +11 -85
- data/lib/picky/indexes/index_indexed.rb +13 -2
- data/lib/picky/indexes/index_indexing.rb +38 -11
- data/lib/picky/loader.rb +0 -4
- data/lib/picky/search.rb +71 -78
- data/lib/picky/tokenizers/base.rb +4 -2
- data/lib/picky.rb +6 -0
- data/spec/lib/application_spec.rb +31 -11
- data/spec/lib/backend/files_spec.rb +1 -1
- data/spec/lib/categories_indexed_spec.rb +2 -2
- data/spec/lib/category_indexed_spec.rb +7 -2
- data/spec/lib/category_indexing_spec.rb +1 -1
- data/spec/lib/category_spec.rb +1 -1
- data/spec/lib/frontend_adapters/rack_spec.rb +4 -4
- data/spec/lib/indexed/bundle/memory_spec.rb +2 -2
- data/spec/lib/indexed/bundle/redis_spec.rb +1 -1
- data/spec/lib/indexed/wrappers/exact_first_spec.rb +2 -2
- data/spec/lib/indexes/index_indexed_spec.rb +25 -3
- data/spec/lib/indexes/index_indexing_spec.rb +58 -10
- data/spec/lib/indexes/index_spec.rb +13 -7
- data/spec/lib/indexes/redis_spec.rb +1 -1
- data/spec/lib/indexing/bundle/memory_partial_generation_speed_spec.rb +1 -1
- data/spec/lib/indexing/bundle/memory_spec.rb +1 -1
- data/spec/lib/indexing/bundle/redis_spec.rb +1 -1
- data/spec/lib/search_spec.rb +18 -18
- data/spec/lib/tokenizers/base_spec.rb +3 -3
- metadata +3 -6
- data/lib/picky/loggers/search.rb +0 -26
- data/spec/lib/loggers/search_spec.rb +0 -19
@@ -7,7 +7,7 @@ module Picky
|
|
7
7
|
# adapter for it.
|
8
8
|
#
|
9
9
|
# For example, if you give it a query, it will extract the query param etc.
|
10
|
-
# and call
|
10
|
+
# and call search on it if it is called by Rack.
|
11
11
|
#
|
12
12
|
module Rack
|
13
13
|
|
@@ -35,9 +35,9 @@ module Picky
|
|
35
35
|
lambda do |env|
|
36
36
|
params = ::Rack::Request.new(env).params
|
37
37
|
|
38
|
-
results = query.
|
38
|
+
results = query.search *extracted(params)
|
39
39
|
|
40
|
-
|
40
|
+
Picky.logger && Picky.logger.info(results.to_log(params[query_key]))
|
41
41
|
|
42
42
|
respond_with results.to_response, content_type
|
43
43
|
end
|
data/lib/picky/adapters/rack.rb
CHANGED
@@ -8,7 +8,7 @@ module Picky
|
|
8
8
|
# adapter for it.
|
9
9
|
#
|
10
10
|
# For example, if you give it a query, it will extract the query param etc.
|
11
|
-
# and call
|
11
|
+
# and call search on it if it is called by Rack.
|
12
12
|
#
|
13
13
|
# Usage:
|
14
14
|
# Adapters::Rack.app_for(thing, options)
|
@@ -18,8 +18,8 @@ module Picky
|
|
18
18
|
# Generates the appropriate app for Rack.
|
19
19
|
#
|
20
20
|
@@mapping = {
|
21
|
-
:
|
22
|
-
:parameters
|
21
|
+
:search => Search,
|
22
|
+
:parameters => LiveParameters
|
23
23
|
}
|
24
24
|
def self.app_for thing, options = {}
|
25
25
|
@@mapping.each_pair do |method, adapter|
|
data/lib/picky/application.rb
CHANGED
@@ -175,7 +175,10 @@ module Picky
|
|
175
175
|
|
176
176
|
# Routes.
|
177
177
|
#
|
178
|
-
|
178
|
+
def route options
|
179
|
+
raise "Warning: block passed into #route method, not into Search.new!" if block_given?
|
180
|
+
rack_adapter.route options
|
181
|
+
end
|
179
182
|
|
180
183
|
# A Picky application implements the Rack interface.
|
181
184
|
#
|
@@ -194,8 +197,7 @@ module Picky
|
|
194
197
|
# Reloads & finalizes the apps.
|
195
198
|
#
|
196
199
|
def reload
|
197
|
-
Loader.load_user 'app' # Sinatra app_file.
|
198
|
-
Loader.load_user 'app/logging' # Standard Picky logging.
|
200
|
+
Loader.load_user 'app' # Sinatra app_file. TODO Needed?
|
199
201
|
Loader.load_user 'app/application' # Standard Picky appfile.
|
200
202
|
finalize_apps
|
201
203
|
exclaim "Application #{apps.map(&:name).join(', ')} loaded."
|
@@ -17,6 +17,13 @@ module Picky
|
|
17
17
|
#
|
18
18
|
def load
|
19
19
|
Yajl::Parser.parse ::File.open(cache_path, 'r'), symbolize_keys: true
|
20
|
+
|
21
|
+
# Note: Circumvents the yajl symbolize utf-8 characters problem.
|
22
|
+
#
|
23
|
+
# Yajl::Parser.parse(::File.open(cache_path, 'r')).inject({}) do |hash, (k, v)|
|
24
|
+
# hash[k.to_sym] = v
|
25
|
+
# hash
|
26
|
+
# end
|
20
27
|
end
|
21
28
|
# Dumps the index hash in json format.
|
22
29
|
#
|
@@ -36,7 +36,7 @@ module Picky
|
|
36
36
|
def retrieve
|
37
37
|
id = nil
|
38
38
|
token = nil
|
39
|
-
::File.open(cache_path, 'r:
|
39
|
+
::File.open(cache_path, 'r:utf-8') do |file|
|
40
40
|
file.each_line do |line|
|
41
41
|
id, token = line.split ?,, 2
|
42
42
|
yield id, (token.chomp! || token).to_sym
|
@@ -47,7 +47,7 @@ module Picky
|
|
47
47
|
#
|
48
48
|
#
|
49
49
|
def open &block
|
50
|
-
::File.open cache_path, 'w:
|
50
|
+
::File.open cache_path, 'w:utf-8', &block
|
51
51
|
end
|
52
52
|
|
53
53
|
|
@@ -1,20 +1,20 @@
|
|
1
1
|
# Extending the Symbol class.
|
2
2
|
#
|
3
3
|
class Symbol # :nodoc:all
|
4
|
-
|
4
|
+
|
5
5
|
# :keys.each_subtoken # => yields each of [:keys, :key, :ke, :k]
|
6
6
|
# :keys.each_subtoken(2) # => yields each of [:keys, :key, :ke]
|
7
7
|
#
|
8
8
|
def each_subtoken from_length = 1
|
9
9
|
sub = self.id2name
|
10
|
-
|
10
|
+
|
11
11
|
size = sub.size
|
12
12
|
from_length = size + from_length + 1 if from_length < 0
|
13
13
|
from_length = size if size < from_length
|
14
14
|
from_length = 1 if from_length < 1
|
15
|
-
|
15
|
+
|
16
16
|
yield self
|
17
17
|
size.downto(from_length + 1) { yield sub.chop!.intern }
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
end
|
data/lib/picky/indexes/index.rb
CHANGED
@@ -99,41 +99,25 @@ module Picky
|
|
99
99
|
# === Parameters
|
100
100
|
# * name: A name that will be used for the index directory and in the Picky front end.
|
101
101
|
#
|
102
|
-
# === Options
|
102
|
+
# === Options (all are used in the block, see examples)
|
103
103
|
# * source: Where the data comes from, e.g. Sources::CSV.new(...). Optional, can be defined in the block using #source.
|
104
104
|
# * result_identifier: Use if you'd like a different identifier/name in the results than the name of the index.
|
105
105
|
# * after_indexing: As of this writing only used in the db source. Executes the given after_indexing as SQL after the indexing process.
|
106
|
-
# * tokenizer:
|
107
|
-
# * key_format:
|
108
|
-
#
|
109
|
-
# Examples:
|
110
|
-
# my_index = Indexes::Memory.new(:my_index, source: some_source) do
|
111
|
-
# category :bla
|
112
|
-
# end
|
106
|
+
# * tokenizer: Call and pass either a tokenizer (responds to #tokenize) or the options for a tokenizer..
|
107
|
+
# * key_format: Call and pass in a format method for the ids (default is #to_i).
|
113
108
|
#
|
109
|
+
# Example:
|
114
110
|
# my_index = Indexes::Memory.new(:my_index) do
|
115
|
-
# source
|
116
|
-
#
|
111
|
+
# source Sources::CSV.new(file: 'data/index.csv')
|
112
|
+
# key_format :to_sym
|
113
|
+
# category :bla
|
114
|
+
# result_identifier :my_special_results
|
117
115
|
# end
|
118
116
|
#
|
119
|
-
#
|
120
117
|
def initialize name, options = {}
|
121
|
-
|
122
|
-
@name = name.to_sym
|
123
|
-
|
124
|
-
check_options options
|
125
|
-
|
126
|
-
@source = options[:source]
|
127
|
-
|
128
|
-
@after_indexing = options[:after_indexing]
|
129
|
-
@tokenizer = options[:tokenizer]
|
130
|
-
@key_format = options[:key_format]
|
131
|
-
|
132
|
-
# Indexed.
|
133
|
-
#
|
134
|
-
@result_identifier = options[:result_identifier] || name
|
118
|
+
@name = name.to_sym
|
135
119
|
|
136
|
-
# TODO Move ignore_unassigned_tokens to query, somehow.
|
120
|
+
# TODO Move ignore_unassigned_tokens to query, somehow. Then, remove options.
|
137
121
|
#
|
138
122
|
@categories = Categories.new ignore_unassigned_tokens: (options[:ignore_unassigned_tokens] || false)
|
139
123
|
|
@@ -141,13 +125,7 @@ module Picky
|
|
141
125
|
#
|
142
126
|
Indexes.register self
|
143
127
|
|
144
|
-
#
|
145
|
-
#
|
146
128
|
instance_eval(&Proc.new) if block_given?
|
147
|
-
|
148
|
-
# Check if any source has been given in the block or the options.
|
149
|
-
#
|
150
|
-
check_source @source
|
151
129
|
end
|
152
130
|
|
153
131
|
# Default bundles.
|
@@ -319,58 +297,6 @@ module Picky
|
|
319
297
|
end
|
320
298
|
alias define_geo_categories geo_categories
|
321
299
|
|
322
|
-
#
|
323
|
-
# Since this is an API, we fail hard quickly.
|
324
|
-
#
|
325
|
-
def check_name name # :nodoc:
|
326
|
-
raise ArgumentError.new(<<-NAME
|
327
|
-
|
328
|
-
|
329
|
-
The index identifier (you gave "#{name}") for Indexes::Memory/Indexes::Redis should be a Symbol/String,
|
330
|
-
Examples:
|
331
|
-
Indexes::Memory.new(:my_cool_index) # Recommended
|
332
|
-
Indexes::Redis.new("a-redis-index")
|
333
|
-
NAME
|
334
|
-
|
335
|
-
|
336
|
-
) unless name.respond_to?(:to_sym)
|
337
|
-
end
|
338
|
-
def check_options options # :nodoc:
|
339
|
-
raise ArgumentError.new(<<-OPTIONS
|
340
|
-
|
341
|
-
|
342
|
-
Sources are not passed in as second parameter for #{self.class.name} anymore, but either
|
343
|
-
* as :source option:
|
344
|
-
#{self.class.name}.new(#{name.inspect}, source: #{options})
|
345
|
-
or
|
346
|
-
* given to the #source method inside the config block:
|
347
|
-
#{self.class.name}.new(#{name.inspect}) do
|
348
|
-
source #{options}
|
349
|
-
end
|
350
|
-
|
351
|
-
Sorry about that breaking change (in 2.2.0), didn't want to go to 3.0.0 yet!
|
352
|
-
|
353
|
-
All the best
|
354
|
-
-- Picky
|
355
|
-
|
356
|
-
|
357
|
-
OPTIONS
|
358
|
-
) unless options.respond_to?(:[])
|
359
|
-
end
|
360
|
-
def check_source source # :nodoc:
|
361
|
-
raise ArgumentError.new(<<-SOURCE
|
362
|
-
|
363
|
-
|
364
|
-
The index "#{name}" should use a data source that responds to either the method #each, or the method #harvest, which yields(id, text), OR it can be a lambda/block, returning such a source.
|
365
|
-
Or it could use one of the built-in sources:
|
366
|
-
Sources::#{(Sources.constants - [:Base, :Wrappers, :NoCSVFileGiven, :NoCouchDBGiven]).join(',
|
367
|
-
Sources::')}
|
368
|
-
|
369
|
-
|
370
|
-
SOURCE
|
371
|
-
) unless source.respond_to?(:each) || source.respond_to?(:harvest) || source.respond_to?(:call)
|
372
|
-
end
|
373
|
-
|
374
300
|
def to_stats # :nodoc:
|
375
301
|
stats = <<-INDEX
|
376
302
|
#{name} (#{self.class}):
|
@@ -390,7 +316,7 @@ module Picky
|
|
390
316
|
#
|
391
317
|
#
|
392
318
|
def to_s
|
393
|
-
"#{self.class}(#{name}, result_id: #{result_identifier}, source: #{source}, categories: #{categories})"
|
319
|
+
"#{self.class}(#{name}, result_id: #{result_identifier}, source: #{@source}, categories: #{categories})"
|
394
320
|
end
|
395
321
|
|
396
322
|
end
|
@@ -6,8 +6,7 @@ module Picky
|
|
6
6
|
#
|
7
7
|
class Index
|
8
8
|
|
9
|
-
attr_reader :
|
10
|
-
:combinator
|
9
|
+
attr_reader :combinator
|
11
10
|
|
12
11
|
delegate :load_from_cache,
|
13
12
|
:analyze,
|
@@ -17,6 +16,18 @@ module Picky
|
|
17
16
|
|
18
17
|
alias reload load_from_cache
|
19
18
|
|
19
|
+
# Define how the results of this index are identified.
|
20
|
+
# (Shown in the client, for example)
|
21
|
+
#
|
22
|
+
# Default is the name of the index.
|
23
|
+
#
|
24
|
+
def result_identifier result_identifier = nil
|
25
|
+
result_identifier ? define_result_identifier(result_identifier) : (@result_identifier || @name)
|
26
|
+
end
|
27
|
+
def define_result_identifier result_identifier
|
28
|
+
@result_identifier = result_identifier
|
29
|
+
end
|
30
|
+
|
20
31
|
end
|
21
32
|
|
22
33
|
end
|
@@ -6,8 +6,7 @@ module Picky
|
|
6
6
|
#
|
7
7
|
class Index
|
8
8
|
|
9
|
-
attr_reader :
|
10
|
-
:bundle_class
|
9
|
+
attr_reader :bundle_class
|
11
10
|
|
12
11
|
# Delegators for indexing.
|
13
12
|
#
|
@@ -35,6 +34,19 @@ module Picky
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
37
|
+
# Define an index tokenizer on the index.
|
38
|
+
#
|
39
|
+
# Parameters are the exact same as for indexing.
|
40
|
+
#
|
41
|
+
def indexing options = {}
|
42
|
+
@tokenizer = if options.respond_to?(:tokenize)
|
43
|
+
options
|
44
|
+
else
|
45
|
+
options && Tokenizers::Index.new(options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias define_indexing indexing
|
49
|
+
|
38
50
|
# Check if the given enumerable source is empty.
|
39
51
|
#
|
40
52
|
# Note: Checking as early as possible to tell the
|
@@ -68,15 +80,6 @@ module Picky
|
|
68
80
|
categories.each &:cache
|
69
81
|
end
|
70
82
|
|
71
|
-
# Define an index tokenizer on the index.
|
72
|
-
#
|
73
|
-
# Parameters are the exact same as for indexing.
|
74
|
-
#
|
75
|
-
def indexing options = {}
|
76
|
-
@tokenizer = Tokenizers::Index.new options
|
77
|
-
end
|
78
|
-
alias define_indexing indexing
|
79
|
-
|
80
83
|
# Returns the installed tokenizer or the default.
|
81
84
|
#
|
82
85
|
def tokenizer
|
@@ -102,6 +105,7 @@ module Picky
|
|
102
105
|
@source = @source.respond_to?(:call) ? @source.call : @source
|
103
106
|
end
|
104
107
|
def define_source source
|
108
|
+
check_source source
|
105
109
|
@source = source
|
106
110
|
end
|
107
111
|
def raise_no_source
|
@@ -119,6 +123,19 @@ module Picky
|
|
119
123
|
NO_SOURCE
|
120
124
|
)
|
121
125
|
end
|
126
|
+
def check_source source # :nodoc:
|
127
|
+
raise ArgumentError.new(<<-SOURCE
|
128
|
+
|
129
|
+
|
130
|
+
The index "#{name}" should use a data source that responds to either the method #each, or the method #harvest, which yields(id, text), OR it can be a lambda/block, returning such a source.
|
131
|
+
Or it could use one of the built-in sources:
|
132
|
+
Sources::#{(Sources.constants - [:Base, :Wrappers, :NoCSVFileGiven, :NoCouchDBGiven]).join(',
|
133
|
+
Sources::')}
|
134
|
+
|
135
|
+
|
136
|
+
SOURCE
|
137
|
+
) unless source.respond_to?(:each) || source.respond_to?(:harvest) || source.respond_to?(:call)
|
138
|
+
end
|
122
139
|
|
123
140
|
# Define a key_format on the index.
|
124
141
|
#
|
@@ -131,6 +148,16 @@ module Picky
|
|
131
148
|
@key_format = key_format
|
132
149
|
end
|
133
150
|
|
151
|
+
# Define what to do after indexing.
|
152
|
+
# (Only used in the Sources::DB)
|
153
|
+
#
|
154
|
+
def after_indexing after_indexing = nil
|
155
|
+
after_indexing ? define_after_indexing(after_indexing) : @after_indexing
|
156
|
+
end
|
157
|
+
def define_after_indexing after_indexing
|
158
|
+
@after_indexing = after_indexing
|
159
|
+
end
|
160
|
+
|
134
161
|
end
|
135
162
|
|
136
163
|
end
|
data/lib/picky/loader.rb
CHANGED
data/lib/picky/search.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
1
3
|
module Picky
|
2
4
|
|
3
|
-
# = Picky
|
5
|
+
# = Picky Searches
|
4
6
|
#
|
5
7
|
# A Picky Search is an object which:
|
6
|
-
#
|
7
|
-
#
|
8
|
+
# * holds one or more indexes
|
9
|
+
# * offers an interface to query these indexes.
|
8
10
|
#
|
9
11
|
# You connect URL paths to indexes via a Query.
|
10
12
|
#
|
11
|
-
# We recommend not
|
13
|
+
# We recommend to not use this directly, but connect it to an URL and query through one of these
|
12
14
|
# (Protip: Use "curl 'localhost:8080/query/path?query=exampletext')" in a Terminal.
|
13
15
|
#
|
14
16
|
class Search
|
@@ -16,39 +18,40 @@ module Picky
|
|
16
18
|
include Helpers::Measuring
|
17
19
|
|
18
20
|
attr_reader :indexes
|
19
|
-
|
20
|
-
attr_accessor :weights
|
21
|
+
attr_accessor :tokenizer, :weights
|
21
22
|
|
22
23
|
# Takes:
|
23
24
|
# * A number of indexes
|
24
|
-
# * Options hash (optional) with:
|
25
|
-
# * tokenizer: Tokenizers::Query.default by default.
|
26
|
-
# * weights: A hash of weights, or a Query::Weights object.
|
27
25
|
#
|
28
26
|
# TODO Add identifiers_to_remove (rename) and reduce_allocations_to_amount (rename).
|
29
27
|
# TODO categories_to_remove ?
|
30
28
|
#
|
31
29
|
# It is also possible to define the tokenizer and weights like so.
|
32
30
|
# Example:
|
33
|
-
# Search.new(index1, index2, index3) do
|
31
|
+
# search = Search.new(index1, index2, index3) do
|
34
32
|
# searching removes_characters: /[^a-z]/, etc.
|
35
33
|
# weights [:author, :title] => +3, [:title, :isbn] => +1
|
36
34
|
# end
|
37
35
|
#
|
38
36
|
def initialize *index_definitions
|
39
|
-
options = Hash === index_definitions.last ? index_definitions.pop : {}
|
40
|
-
|
41
37
|
@indexes = Query::Indexes.new *index_definitions, combinations_type_for(index_definitions)
|
42
|
-
searching options[:tokenizer]
|
43
|
-
boost options[:weights]
|
44
38
|
|
45
39
|
instance_eval(&Proc.new) if block_given?
|
40
|
+
|
41
|
+
@tokenizer ||= Tokenizers::Query.default
|
42
|
+
@weights ||= Query::Weights.new
|
43
|
+
|
44
|
+
self
|
46
45
|
end
|
47
46
|
|
48
|
-
#
|
49
|
-
# Search.new(index1, index2, index3) do
|
50
|
-
# searching removes_characters: /[^a-z]/,
|
51
|
-
#
|
47
|
+
# Examples:
|
48
|
+
# search = Search.new(index1, index2, index3) do
|
49
|
+
# searching removes_characters: /[^a-z]/,
|
50
|
+
# # etc.
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# search = Search.new(index1, index2, index3) do
|
54
|
+
# searching MyTokenizerThatRespondsToTheMethodTokenize.new
|
52
55
|
# end
|
53
56
|
#
|
54
57
|
def searching options
|
@@ -59,63 +62,17 @@ module Picky
|
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
62
|
-
# Returns the tokenizer if set or if not, the query tokenizer.
|
63
|
-
#
|
64
|
-
def tokenizer
|
65
|
-
@tokenizer || Tokenizers::Query.default
|
66
|
-
end
|
67
|
-
|
68
65
|
# Example:
|
69
|
-
# Search.new(
|
70
|
-
#
|
71
|
-
#
|
66
|
+
# search = Search.new(books_index, dvd_index, mp3_index) do
|
67
|
+
# boost [:author, :title] => +3,
|
68
|
+
# [:title, :isbn] => +1
|
72
69
|
# end
|
73
70
|
#
|
74
|
-
def boost
|
75
|
-
weights
|
71
|
+
def boost weights
|
72
|
+
weights ||= Query::Weights.new
|
76
73
|
@weights = Hash === weights ? Query::Weights.new(weights) : weights
|
77
74
|
end
|
78
75
|
|
79
|
-
# Returns the right combinations strategy for
|
80
|
-
# a number of query indexes.
|
81
|
-
#
|
82
|
-
# Currently it isn't possible using Memory and Redis etc.
|
83
|
-
# indexes in the same query index group.
|
84
|
-
#
|
85
|
-
# Picky will raise a Query::Indexes::DifferentTypesError.
|
86
|
-
#
|
87
|
-
@@mapping = {
|
88
|
-
Indexes::Memory => Query::Combinations::Memory,
|
89
|
-
Indexes::Redis => Query::Combinations::Redis
|
90
|
-
}
|
91
|
-
def combinations_type_for index_definitions_ary
|
92
|
-
index_types = extract_index_types index_definitions_ary
|
93
|
-
!index_types.empty? && @@mapping[*index_types] || Query::Combinations::Memory
|
94
|
-
end
|
95
|
-
def extract_index_types index_definitions_ary
|
96
|
-
index_types = index_definitions_ary.map(&:class)
|
97
|
-
index_types.uniq!
|
98
|
-
check_index_types index_types
|
99
|
-
index_types
|
100
|
-
end
|
101
|
-
def check_index_types index_types
|
102
|
-
raise_different index_types if index_types.size > 1
|
103
|
-
end
|
104
|
-
# Currently it isn't possible using Memory and Redis etc.
|
105
|
-
# indexes in the same query index group.
|
106
|
-
#
|
107
|
-
class DifferentTypesError < StandardError
|
108
|
-
def initialize types
|
109
|
-
@types = types
|
110
|
-
end
|
111
|
-
def to_s
|
112
|
-
"Currently it isn't possible to mix #{@types.join(" and ")} Indexes in the same Search instance."
|
113
|
-
end
|
114
|
-
end
|
115
|
-
def raise_different index_types
|
116
|
-
raise DifferentTypesError.new(index_types)
|
117
|
-
end
|
118
|
-
|
119
76
|
# This is the main entry point for a query.
|
120
77
|
# Use this in specs and also for running queries.
|
121
78
|
#
|
@@ -126,19 +83,15 @@ module Picky
|
|
126
83
|
#
|
127
84
|
# Note: The Rack adapter calls this method after unravelling the HTTP request.
|
128
85
|
#
|
129
|
-
|
130
|
-
|
131
|
-
def search_with_text text, ids = 20, offset = 0
|
132
|
-
search tokenized(text), ids.to_i, offset.to_i
|
86
|
+
def search text, ids = 20, offset = 0
|
87
|
+
search_with tokenized(text), ids.to_i, offset.to_i
|
133
88
|
end
|
134
89
|
|
135
90
|
# Runs the actual search using Query::Tokens.
|
136
91
|
#
|
137
|
-
# Note: Internal method, use #
|
92
|
+
# Note: Internal method, use #search
|
138
93
|
#
|
139
|
-
|
140
|
-
#
|
141
|
-
def search tokens, ids = 20, offset = 0
|
94
|
+
def search_with tokens, ids = 20, offset = 0
|
142
95
|
results = nil
|
143
96
|
|
144
97
|
duration = timed do
|
@@ -151,7 +104,7 @@ module Picky
|
|
151
104
|
|
152
105
|
# Execute a search using Query::Tokens.
|
153
106
|
#
|
154
|
-
# Note: Internal method, use #
|
107
|
+
# Note: Internal method, use #search.
|
155
108
|
#
|
156
109
|
def execute tokens, ids, offset
|
157
110
|
Results.from ids, offset, sorted_allocations(tokens)
|
@@ -172,6 +125,46 @@ module Picky
|
|
172
125
|
indexes.prepared_allocations_for tokens, weights
|
173
126
|
end
|
174
127
|
|
128
|
+
# Returns the right combinations strategy for
|
129
|
+
# a number of query indexes.
|
130
|
+
#
|
131
|
+
# Currently it isn't possible using Memory and Redis etc.
|
132
|
+
# indexes in the same query index group.
|
133
|
+
#
|
134
|
+
# Picky will raise a Query::Indexes::DifferentTypesError.
|
135
|
+
#
|
136
|
+
@@mapping = {
|
137
|
+
Indexes::Memory => Query::Combinations::Memory,
|
138
|
+
Indexes::Redis => Query::Combinations::Redis
|
139
|
+
}
|
140
|
+
def combinations_type_for index_definitions_ary
|
141
|
+
index_types = extract_index_types index_definitions_ary
|
142
|
+
!index_types.empty? && @@mapping[*index_types] || Query::Combinations::Memory
|
143
|
+
end
|
144
|
+
def extract_index_types index_definitions_ary
|
145
|
+
index_types = index_definitions_ary.map(&:class)
|
146
|
+
index_types.uniq!
|
147
|
+
check_index_types index_types
|
148
|
+
index_types
|
149
|
+
end
|
150
|
+
def check_index_types index_types
|
151
|
+
raise_different index_types if index_types.size > 1
|
152
|
+
end
|
153
|
+
# Currently it isn't possible using Memory and Redis etc.
|
154
|
+
# indexes in the same query index group.
|
155
|
+
#
|
156
|
+
class DifferentTypesError < StandardError
|
157
|
+
def initialize types
|
158
|
+
@types = types
|
159
|
+
end
|
160
|
+
def to_s
|
161
|
+
"Currently it isn't possible to mix #{@types.join(" and ")} Indexes in the same Search instance."
|
162
|
+
end
|
163
|
+
end
|
164
|
+
def raise_different index_types
|
165
|
+
raise DifferentTypesError.new(index_types)
|
166
|
+
end
|
167
|
+
|
175
168
|
# Display some nice information for the user.
|
176
169
|
#
|
177
170
|
def to_s
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
1
3
|
module Picky
|
2
4
|
|
3
5
|
module Tokenizers # :nodoc:all
|
@@ -120,7 +122,7 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
|
|
120
122
|
#
|
121
123
|
# Note: Currently only for indexing.
|
122
124
|
#
|
123
|
-
def
|
125
|
+
def rejects_token_if &condition
|
124
126
|
@reject_condition = condition
|
125
127
|
end
|
126
128
|
def reject tokens
|
@@ -170,7 +172,7 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
|
|
170
172
|
# Defaults.
|
171
173
|
#
|
172
174
|
splits_text_on options[:splits_text_on] || /\s/
|
173
|
-
|
175
|
+
rejects_token_if &(options[:rejects_token_if] || :blank?)
|
174
176
|
end
|
175
177
|
|
176
178
|
# Default preprocessing hook.
|