friendlyfashion-thinking-sphinx 2.0.13.3 → 2.0.14.1
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.
- checksums.yaml +15 -0
- data/HISTORY +12 -5
- data/README.textile +1 -0
- data/features/attribute_updates.feature +15 -13
- data/features/deleting_instances.feature +12 -9
- data/features/handling_edits.feature +20 -17
- data/features/searching_by_index.feature +6 -5
- data/features/step_definitions/common_steps.rb +4 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +5 -4
- data/lib/thinking_sphinx/active_record.rb +3 -3
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +7 -0
- data/lib/thinking_sphinx/bundled_search.rb +6 -10
- data/lib/thinking_sphinx/configuration.rb +1 -20
- data/lib/thinking_sphinx/connection.rb +71 -0
- data/lib/thinking_sphinx/context.rb +7 -2
- data/lib/thinking_sphinx/search.rb +24 -14
- data/lib/thinking_sphinx/version.rb +1 -1
- data/lib/thinking_sphinx.rb +2 -0
- data/spec/thinking_sphinx/active_record/delta_spec.rb +1 -1
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +2 -1
- data/spec/thinking_sphinx/active_record_spec.rb +2 -2
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +18 -0
- data/spec/thinking_sphinx/configuration_spec.rb +0 -68
- data/spec/thinking_sphinx/connection_spec.rb +77 -0
- data/spec/thinking_sphinx/context_spec.rb +4 -3
- data/spec/thinking_sphinx/facet_search_spec.rb +25 -25
- data/spec/thinking_sphinx/search_methods_spec.rb +34 -34
- data/spec/thinking_sphinx/search_spec.rb +4 -16
- metadata +22 -29
@@ -53,7 +53,7 @@ module ThinkingSphinx
|
|
53
53
|
|
54
54
|
SourceOptions = Riddle::Configuration::SQLSource.settings.map { |setting|
|
55
55
|
setting.to_s
|
56
|
-
} - %w( type
|
56
|
+
} - %w( type sql_query sql_joined_field sql_file_field
|
57
57
|
sql_query_range sql_attr_uint sql_attr_bool sql_attr_bigint sql_query_info
|
58
58
|
sql_attr_timestamp sql_attr_str2ordinal sql_attr_float sql_attr_multi
|
59
59
|
sql_attr_string sql_attr_str2wordcount sql_column_buffers sql_field_string
|
@@ -263,14 +263,6 @@ module ThinkingSphinx
|
|
263
263
|
|
264
264
|
attr_accessor :timeout
|
265
265
|
|
266
|
-
def client
|
267
|
-
client = Riddle::Client.new shuffled_addresses, port,
|
268
|
-
configuration.searchd.client_key
|
269
|
-
client.max_matches = configuration.searchd.max_matches || 1000
|
270
|
-
client.timeout = timeout || 0
|
271
|
-
client
|
272
|
-
end
|
273
|
-
|
274
266
|
def models_by_crc
|
275
267
|
@models_by_crc ||= begin
|
276
268
|
ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
|
@@ -347,17 +339,6 @@ module ThinkingSphinx
|
|
347
339
|
}
|
348
340
|
end
|
349
341
|
|
350
|
-
def shuffled_addresses
|
351
|
-
return address unless shuffle
|
352
|
-
|
353
|
-
addresses = Array(address)
|
354
|
-
if addresses.respond_to?(:shuffle)
|
355
|
-
addresses.shuffle
|
356
|
-
else
|
357
|
-
address.sort_by { rand }
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
342
|
def initial_model_directories
|
362
343
|
directories = ["#{app_root}/app/models/"] +
|
363
344
|
Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class ThinkingSphinx::Connection
|
2
|
+
def self.pool
|
3
|
+
@pool ||= Innertube::Pool.new(
|
4
|
+
Proc.new { Rails.logger.debug '>>> CONNECTING <<<'; ThinkingSphinx::Connection.new },
|
5
|
+
Proc.new { |connection| connection.close }
|
6
|
+
)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.take
|
10
|
+
retries = 0
|
11
|
+
original = nil
|
12
|
+
begin
|
13
|
+
pool.take do |connection|
|
14
|
+
connection.reset
|
15
|
+
begin
|
16
|
+
yield connection
|
17
|
+
rescue Riddle::ConnectionError, Riddle::ResponseError => error
|
18
|
+
original = error
|
19
|
+
raise Innertube::Pool::BadResource
|
20
|
+
end
|
21
|
+
end
|
22
|
+
rescue Innertube::Pool::BadResource
|
23
|
+
retries += 1
|
24
|
+
retry if retries < 3
|
25
|
+
raise original
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
client.open
|
31
|
+
end
|
32
|
+
|
33
|
+
def client
|
34
|
+
@client ||= begin
|
35
|
+
client = Riddle::Client.new shuffled_addresses, configuration.port,
|
36
|
+
client_key
|
37
|
+
client.max_matches = _max_matches
|
38
|
+
client.timeout = configuration.timeout || 0
|
39
|
+
client
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def client_key
|
46
|
+
configuration.configuration.searchd.client_key
|
47
|
+
end
|
48
|
+
|
49
|
+
def configuration
|
50
|
+
ThinkingSphinx::Configuration.instance
|
51
|
+
end
|
52
|
+
|
53
|
+
def _max_matches
|
54
|
+
configuration.configuration.searchd.max_matches || 1000
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method, *arguments, &block)
|
58
|
+
client.send method, *arguments, &block
|
59
|
+
end
|
60
|
+
|
61
|
+
def shuffled_addresses
|
62
|
+
return configuration.address unless configuration.shuffle
|
63
|
+
|
64
|
+
addresses = Array(configuration.address)
|
65
|
+
if addresses.respond_to?(:shuffle)
|
66
|
+
addresses.shuffle
|
67
|
+
else
|
68
|
+
address.sort_by { rand }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -62,9 +62,14 @@ class ThinkingSphinx::Context
|
|
62
62
|
|
63
63
|
begin
|
64
64
|
camelized_model.constantize
|
65
|
-
rescue LoadError
|
65
|
+
rescue LoadError, NameError
|
66
66
|
# Make sure that STI subclasses in subfolders are loaded.
|
67
|
-
|
67
|
+
if camelized_model.gsub!(/.+::/, '').nil?
|
68
|
+
STDERR.puts "ThinkingSphinx: error loading #{file}"
|
69
|
+
next
|
70
|
+
else
|
71
|
+
retry
|
72
|
+
end
|
68
73
|
rescue Exception => err
|
69
74
|
STDERR.puts "Warning: Error loading #{file}:"
|
70
75
|
STDERR.puts err.message
|
@@ -359,13 +359,15 @@ module ThinkingSphinx
|
|
359
359
|
populate
|
360
360
|
|
361
361
|
index = options[:index] || "#{model.core_index_names.first}"
|
362
|
-
client
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
362
|
+
take_client do |client|
|
363
|
+
client.excerpts(
|
364
|
+
{
|
365
|
+
:docs => [string.to_s],
|
366
|
+
:words => query,
|
367
|
+
:index => index.split(',').first.strip
|
368
|
+
}.merge(options[:excerpt_options] || {})
|
369
|
+
).first
|
370
|
+
end
|
369
371
|
end
|
370
372
|
|
371
373
|
def search(*args)
|
@@ -391,10 +393,16 @@ module ThinkingSphinx
|
|
391
393
|
ThinkingSphinx::FacetSearch.new(*args)
|
392
394
|
end
|
393
395
|
|
394
|
-
def
|
395
|
-
|
396
|
-
|
397
|
-
|
396
|
+
def take_client
|
397
|
+
if options[:client]
|
398
|
+
prepare options[:client]
|
399
|
+
yield options[:client]
|
400
|
+
else
|
401
|
+
ThinkingSphinx::Connection.take do |client|
|
402
|
+
prepare client
|
403
|
+
yield client
|
404
|
+
end
|
405
|
+
end
|
398
406
|
end
|
399
407
|
|
400
408
|
def append_to(client)
|
@@ -426,12 +434,14 @@ module ThinkingSphinx
|
|
426
434
|
retry_on_stale_index do
|
427
435
|
retry_on_index_not_preread do
|
428
436
|
begin
|
437
|
+
@results = nil
|
429
438
|
log query do
|
430
|
-
|
439
|
+
take_client do |client|
|
440
|
+
@results = client.query query, indexes, comment
|
441
|
+
end
|
431
442
|
end
|
432
443
|
total = @results[:total_found].to_i
|
433
444
|
log "Found #{total} result#{'s' unless total == 1}"
|
434
|
-
|
435
445
|
log "Sphinx Daemon returned warning: #{warning}" if warning?
|
436
446
|
|
437
447
|
if error?
|
@@ -470,7 +480,7 @@ module ThinkingSphinx
|
|
470
480
|
replace instances_from_matches
|
471
481
|
add_excerpter
|
472
482
|
add_sphinx_attributes
|
473
|
-
add_matching_fields if
|
483
|
+
add_matching_fields if options[:rank_mode] == :fieldmask
|
474
484
|
end
|
475
485
|
end
|
476
486
|
|
data/lib/thinking_sphinx.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'active_record'
|
3
|
+
require 'innertube'
|
3
4
|
require 'yaml'
|
4
5
|
require 'riddle'
|
5
6
|
|
@@ -11,6 +12,7 @@ require 'thinking_sphinx/association'
|
|
11
12
|
require 'thinking_sphinx/attribute'
|
12
13
|
require 'thinking_sphinx/bundled_search'
|
13
14
|
require 'thinking_sphinx/configuration'
|
15
|
+
require 'thinking_sphinx/connection'
|
14
16
|
require 'thinking_sphinx/context'
|
15
17
|
require 'thinking_sphinx/excerpter'
|
16
18
|
require 'thinking_sphinx/facet'
|
@@ -78,7 +78,7 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
|
|
78
78
|
|
79
79
|
@client = Riddle::Client.new
|
80
80
|
@client.stub!(:update => true)
|
81
|
-
ThinkingSphinx::
|
81
|
+
ThinkingSphinx::Connection.stub(:take).and_yield @client
|
82
82
|
end
|
83
83
|
|
84
84
|
it "shouldn't index if delta indexing is disabled" do
|
@@ -142,7 +142,8 @@ describe ThinkingSphinx::ActiveRecord::Scopes do
|
|
142
142
|
@config = ThinkingSphinx::Configuration.instance
|
143
143
|
@client = Riddle::Client.new
|
144
144
|
|
145
|
-
|
145
|
+
ThinkingSphinx::Connection.stub(:take).and_yield(@client)
|
146
|
+
|
146
147
|
@client.stub!(:query => {:matches => [], :total_found => 43})
|
147
148
|
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
148
149
|
Alpha.sphinx_scope(:ids_only) { {:ids_only => true} }
|
@@ -271,7 +271,7 @@ describe ThinkingSphinx::ActiveRecord do
|
|
271
271
|
@client.stub!(:update => true)
|
272
272
|
@person = Person.find(:first)
|
273
273
|
|
274
|
-
|
274
|
+
ThinkingSphinx::Connection.stub(:take).and_yield(@client)
|
275
275
|
Person.sphinx_indexes.each { |index| index.stub!(:delta? => false) }
|
276
276
|
end
|
277
277
|
|
@@ -481,7 +481,7 @@ describe ThinkingSphinx::ActiveRecord do
|
|
481
481
|
before :each do
|
482
482
|
@client = stub('client')
|
483
483
|
ThinkingSphinx.stub!(:sphinx_running? => true)
|
484
|
-
ThinkingSphinx::
|
484
|
+
ThinkingSphinx::Connection.stub(:take).and_yield(@client)
|
485
485
|
end
|
486
486
|
|
487
487
|
it "should direct the update to the supplied index" do
|
@@ -127,6 +127,24 @@ describe ThinkingSphinx::AbstractAdapter do
|
|
127
127
|
should == :postgresql
|
128
128
|
end
|
129
129
|
|
130
|
+
it "translates a JDBC adapter with MySQL connection string to MySQL" do
|
131
|
+
klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
|
132
|
+
connection.stub(:config => {:adapter => 'jdbc',
|
133
|
+
:url => 'jdbc:mysql://127.0.0.1:3306/sphinx'})
|
134
|
+
|
135
|
+
ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
|
136
|
+
should == :mysql
|
137
|
+
end
|
138
|
+
|
139
|
+
it "translates a JDBC adapter with PostgresSQL connection string to PostgresSQL" do
|
140
|
+
klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
|
141
|
+
connection.stub(:config => {:adapter => 'jdbc',
|
142
|
+
:url => 'jdbc:postgresql://127.0.0.1:3306/sphinx'})
|
143
|
+
|
144
|
+
ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
|
145
|
+
should == :postgresql
|
146
|
+
end
|
147
|
+
|
130
148
|
it "returns other JDBC adapters without translation" do
|
131
149
|
klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
|
132
150
|
connection.stub(:config => {:adapter => 'jdbcmssql'})
|
@@ -241,74 +241,6 @@ describe ThinkingSphinx::Configuration do
|
|
241
241
|
end
|
242
242
|
end
|
243
243
|
|
244
|
-
describe '#client' do
|
245
|
-
before :each do
|
246
|
-
@config = ThinkingSphinx::Configuration.instance
|
247
|
-
@config.address = 'domain.url'
|
248
|
-
@config.port = 3333
|
249
|
-
@config.configuration.searchd.max_matches = 100
|
250
|
-
@config.timeout = 1
|
251
|
-
end
|
252
|
-
|
253
|
-
it "should return an instance of Riddle::Client" do
|
254
|
-
@config.client.should be_a(Riddle::Client)
|
255
|
-
end
|
256
|
-
|
257
|
-
it "should use the configuration address" do
|
258
|
-
@config.client.server.should == 'domain.url'
|
259
|
-
end
|
260
|
-
|
261
|
-
it "should use the configuration port" do
|
262
|
-
@config.client.port.should == 3333
|
263
|
-
end
|
264
|
-
|
265
|
-
it "should use the configuration max matches" do
|
266
|
-
@config.client.max_matches.should == 100
|
267
|
-
end
|
268
|
-
|
269
|
-
it "should use the configuration timeout" do
|
270
|
-
@config.client.timeout.should == 1
|
271
|
-
end
|
272
|
-
|
273
|
-
describe 'when shuffle is enabled' do
|
274
|
-
let(:client) { double('client', :max_matches= => nil, :timeout= => nil) }
|
275
|
-
|
276
|
-
before :each do
|
277
|
-
@config.shuffle = true
|
278
|
-
end
|
279
|
-
|
280
|
-
it "should shuffle client servers" do
|
281
|
-
@config.address = ['1.1.1.1', '2.2.2.2']
|
282
|
-
@config.address.stub!(:shuffle => ['2.2.2.2', '1.1.1.1'])
|
283
|
-
|
284
|
-
Riddle::Client.should_receive(:new) do |addresses, port, key|
|
285
|
-
addresses.should == ['2.2.2.2', '1.1.1.1']
|
286
|
-
client
|
287
|
-
end
|
288
|
-
@config.client
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
describe 'when shuffle is disabled' do
|
293
|
-
let(:client) { double('client', :max_matches= => nil, :timeout= => nil) }
|
294
|
-
|
295
|
-
before :each do
|
296
|
-
@config.shuffle = false
|
297
|
-
end
|
298
|
-
|
299
|
-
it "should not shuffle client servers" do
|
300
|
-
@config.address = ['1.1.1.1', '2.2.2.2.', '3.3.3.3', '4.4.4.4', '5.5.5.5']
|
301
|
-
|
302
|
-
@config.address.should_not_receive(:shuffle)
|
303
|
-
Riddle::Client.should_receive(:new) do |addresses, port, key|
|
304
|
-
addresses.should == ['1.1.1.1', '2.2.2.2.', '3.3.3.3', '4.4.4.4', '5.5.5.5']
|
305
|
-
client
|
306
|
-
end
|
307
|
-
@config.client
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
244
|
describe '#models_by_crc' do
|
313
245
|
before :each do
|
314
246
|
@config = ThinkingSphinx::Configuration.instance
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Connection do
|
4
|
+
describe '#client' do
|
5
|
+
let(:connection) { ThinkingSphinx::Connection.new }
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@config = ThinkingSphinx::Configuration.instance
|
9
|
+
@config.address = 'domain.url'
|
10
|
+
@config.port = 3333
|
11
|
+
@config.configuration.searchd.max_matches = 100
|
12
|
+
@config.timeout = 1
|
13
|
+
|
14
|
+
pending
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return an instance of Riddle::Client" do
|
18
|
+
connection.client.should be_a(Riddle::Client)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should use the configuration address" do
|
22
|
+
connection.client.server.should == 'domain.url'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should use the configuration port" do
|
26
|
+
connection.client.port.should == 3333
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should use the configuration max matches" do
|
30
|
+
connection.client.max_matches.should == 100
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should use the configuration timeout" do
|
34
|
+
connection.client.timeout.should == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'when shuffle is enabled' do
|
38
|
+
let(:client) { double('client', :max_matches= => nil, :timeout= => nil,
|
39
|
+
:open => true) }
|
40
|
+
|
41
|
+
before :each do
|
42
|
+
@config.shuffle = true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should shuffle client servers" do
|
46
|
+
@config.address = ['1.1.1.1', '2.2.2.2']
|
47
|
+
@config.address.stub!(:shuffle => ['2.2.2.2', '1.1.1.1'])
|
48
|
+
|
49
|
+
Riddle::Client.should_receive(:new) do |addresses, port, key|
|
50
|
+
addresses.should == ['2.2.2.2', '1.1.1.1']
|
51
|
+
client
|
52
|
+
end
|
53
|
+
connection.client
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'when shuffle is disabled' do
|
58
|
+
let(:client) { double('client', :max_matches= => nil, :timeout= => nil,
|
59
|
+
:open => true) }
|
60
|
+
|
61
|
+
before :each do
|
62
|
+
@config.shuffle = false
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should not shuffle client servers" do
|
66
|
+
@config.address = ['1.1.1.1', '2.2.2.2.', '3.3.3.3', '4.4.4.4', '5.5.5.5']
|
67
|
+
|
68
|
+
@config.address.should_not_receive(:shuffle)
|
69
|
+
Riddle::Client.should_receive(:new) do |addresses, port, key|
|
70
|
+
addresses.should == ['1.1.1.1', '2.2.2.2.', '3.3.3.3', '4.4.4.4', '5.5.5.5']
|
71
|
+
client
|
72
|
+
end
|
73
|
+
connection.client
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -34,16 +34,17 @@ describe ThinkingSphinx::Context do
|
|
34
34
|
it "should report name errors but not raise them" do
|
35
35
|
class_name.stub(:constantize).and_raise(NameError)
|
36
36
|
STDERR.stub!(:puts => '')
|
37
|
-
STDERR.should_receive(:puts).with('
|
37
|
+
STDERR.should_receive(:puts).with('ThinkingSphinx: error loading a.rb')
|
38
38
|
|
39
39
|
lambda {
|
40
40
|
ts_context.prepare
|
41
41
|
}.should_not raise_error
|
42
42
|
end
|
43
43
|
|
44
|
-
it "should
|
45
|
-
model_name_lower.should_receive(:gsub!).twice.and_return(true, nil)
|
44
|
+
it "should report load errors but not raise them" do
|
46
45
|
class_name.stub(:constantize).and_raise(LoadError)
|
46
|
+
STDERR.stub!(:puts => '')
|
47
|
+
STDERR.should_receive(:puts).with('ThinkingSphinx: error loading a.rb')
|
47
48
|
|
48
49
|
lambda {
|
49
50
|
ts_context.prepare
|