freelancing-god-thinking-sphinx 1.1.21 → 1.1.22
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +9 -0
- data/lib/thinking_sphinx.rb +33 -1
- data/lib/thinking_sphinx/attribute.rb +32 -9
- data/lib/thinking_sphinx/configuration.rb +8 -2
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +2 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +1 -1
- data/lib/thinking_sphinx/search.rb +2 -2
- data/lib/thinking_sphinx/tasks.rb +4 -4
- data/spec/unit/thinking_sphinx/attribute_spec.rb +20 -0
- data/spec/unit/thinking_sphinx/configuration_spec.rb +6 -4
- data/spec/unit/thinking_sphinx_spec.rb +16 -0
- metadata +2 -2
data/README.textile
CHANGED
@@ -25,11 +25,18 @@ Then install the ginger gem. The steps are the same, except that you might need
|
|
25
25
|
cd ginger
|
26
26
|
rake gem
|
27
27
|
sudo gem install pkg/ginger-1.1.0.gem
|
28
|
+
|
29
|
+
Alternatively, install the ginger gem directly from the freelancing-god github repository
|
30
|
+
|
31
|
+
sudo gem sources -a http://gems.github.com
|
32
|
+
sudo gem install freelancing-god-ginger
|
28
33
|
|
29
34
|
Then set up your database:
|
30
35
|
|
31
36
|
cp spec/fixtures/database.yml.default spec/fixtures/database.yml
|
32
37
|
mysqladmin -u root create thinking_sphinx
|
38
|
+
|
39
|
+
This last step can be done automatically by the contribute.rb script if all dependencies are met.
|
33
40
|
|
34
41
|
Make sure you don't have another Sphinx daemon (searchd) running. If you do, quit it with "rake ts:stop"
|
35
42
|
in the app root.
|
@@ -132,3 +139,5 @@ Since I first released this library, there's been quite a few people who have su
|
|
132
139
|
* Tien Dung
|
133
140
|
* Johannes Kaefer
|
134
141
|
* Paul Campbell
|
142
|
+
* Matthew Beale
|
143
|
+
* Tom Simnett
|
data/lib/thinking_sphinx.rb
CHANGED
@@ -37,7 +37,7 @@ module ThinkingSphinx
|
|
37
37
|
module Version #:nodoc:
|
38
38
|
Major = 1
|
39
39
|
Minor = 1
|
40
|
-
Tiny =
|
40
|
+
Tiny = 22
|
41
41
|
|
42
42
|
String = [Major, Minor, Tiny].join('.')
|
43
43
|
end
|
@@ -138,7 +138,39 @@ module ThinkingSphinx
|
|
138
138
|
)
|
139
139
|
end
|
140
140
|
|
141
|
+
@@remote_sphinx = false
|
142
|
+
|
143
|
+
# An indication of whether Sphinx is running on a remote machine instead of
|
144
|
+
# the same machine.
|
145
|
+
#
|
146
|
+
def self.remote_sphinx?
|
147
|
+
@@remote_sphinx
|
148
|
+
end
|
149
|
+
|
150
|
+
# Tells Thinking Sphinx that Sphinx is running on a different machine, and
|
151
|
+
# thus it can't reliably guess whether it is running or not (ie: the
|
152
|
+
# #sphinx_running? method), and so just assumes it is.
|
153
|
+
#
|
154
|
+
# Useful for multi-machine deployments. Set it in your production.rb file.
|
155
|
+
#
|
156
|
+
# ThinkingSphinx.remote_sphinx = true
|
157
|
+
#
|
158
|
+
def self.remote_sphinx=(value)
|
159
|
+
@@remote_sphinx = value
|
160
|
+
end
|
161
|
+
|
162
|
+
# Check if Sphinx is running. If remote_sphinx is set to true (indicating
|
163
|
+
# Sphinx is on a different machine), this will always return true, and you
|
164
|
+
# will have to handle any connection errors yourself.
|
165
|
+
#
|
141
166
|
def self.sphinx_running?
|
167
|
+
remote_sphinx? || sphinx_running_by_pid?
|
168
|
+
end
|
169
|
+
|
170
|
+
# Check if Sphinx is actually running, provided the pid is on the same
|
171
|
+
# machine as this code.
|
172
|
+
#
|
173
|
+
def self.sphinx_running_by_pid?
|
142
174
|
!!sphinx_pid && pid_active?(sphinx_pid)
|
143
175
|
end
|
144
176
|
|
@@ -127,7 +127,7 @@ module ThinkingSphinx
|
|
127
127
|
def config_value(offset = nil)
|
128
128
|
if type == :multi
|
129
129
|
multi_config = include_as_association? ? "field" :
|
130
|
-
source_value(offset).gsub(/\
|
130
|
+
source_value(offset).gsub(/\s+/m, " ").strip
|
131
131
|
"uint #{unique_name} from #{multi_config}"
|
132
132
|
else
|
133
133
|
unique_name
|
@@ -194,24 +194,25 @@ module ThinkingSphinx
|
|
194
194
|
end
|
195
195
|
|
196
196
|
def query(offset)
|
197
|
-
|
198
|
-
|
197
|
+
base_assoc = base_association_for_mva
|
198
|
+
end_assoc = end_association_for_mva
|
199
|
+
raise "Could not determine SQL for MVA" if base_assoc.nil?
|
199
200
|
|
200
201
|
<<-SQL
|
201
|
-
SELECT #{foreign_key_for_mva
|
202
|
+
SELECT #{foreign_key_for_mva base_assoc}
|
202
203
|
#{ThinkingSphinx.unique_id_expression(offset)} AS #{quote_column('id')},
|
203
|
-
#{primary_key_for_mva(
|
204
|
-
FROM #{quote_table_name
|
204
|
+
#{primary_key_for_mva(end_assoc)} AS #{quote_column(unique_name)}
|
205
|
+
FROM #{quote_table_name base_assoc.table} #{association_joins}
|
205
206
|
SQL
|
206
207
|
end
|
207
208
|
|
208
209
|
def query_clause
|
209
|
-
foreign_key = foreign_key_for_mva
|
210
|
+
foreign_key = foreign_key_for_mva base_association_for_mva
|
210
211
|
"WHERE #{foreign_key} >= $start AND #{foreign_key} <= $end"
|
211
212
|
end
|
212
213
|
|
213
214
|
def range_query
|
214
|
-
assoc =
|
215
|
+
assoc = base_association_for_mva
|
215
216
|
foreign_key = foreign_key_for_mva assoc
|
216
217
|
"SELECT MIN(#{foreign_key}), MAX(#{foreign_key}) FROM #{quote_table_name assoc.table}"
|
217
218
|
end
|
@@ -226,12 +227,34 @@ FROM #{quote_table_name assoc.table}
|
|
226
227
|
quote_with_table assoc.table, assoc.reflection.primary_key_name
|
227
228
|
end
|
228
229
|
|
229
|
-
def
|
230
|
+
def end_association_for_mva
|
230
231
|
@association_for_mva ||= associations[columns.first].detect { |assoc|
|
231
232
|
assoc.has_column?(columns.first.__name)
|
232
233
|
}
|
233
234
|
end
|
234
235
|
|
236
|
+
def base_association_for_mva
|
237
|
+
@first_association_for_mva ||= begin
|
238
|
+
assoc = end_association_for_mva
|
239
|
+
while !assoc.parent.nil?
|
240
|
+
assoc = assoc.parent
|
241
|
+
end
|
242
|
+
|
243
|
+
assoc
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def association_joins
|
248
|
+
joins = []
|
249
|
+
assoc = end_association_for_mva
|
250
|
+
while assoc != base_association_for_mva
|
251
|
+
joins << assoc.to_sql
|
252
|
+
assoc = assoc.parent
|
253
|
+
end
|
254
|
+
|
255
|
+
joins.join(' ')
|
256
|
+
end
|
257
|
+
|
235
258
|
def is_many_ints?
|
236
259
|
concat_ws? && all_ints?
|
237
260
|
end
|
@@ -25,6 +25,8 @@ module ThinkingSphinx
|
|
25
25
|
# ignore chars:: nil
|
26
26
|
# html strip:: false
|
27
27
|
# html remove elements:: ''
|
28
|
+
# searchd_binary_name:: searchd
|
29
|
+
# indexer_binary_name:: indexer
|
28
30
|
#
|
29
31
|
# If you want to change these settings, create a YAML file at
|
30
32
|
# config/sphinx.yml with settings for each environment, in a similar
|
@@ -32,7 +34,8 @@ module ThinkingSphinx
|
|
32
34
|
# searchd_log_file, query_log_file, pid_file, searchd_file_path, port,
|
33
35
|
# allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit,
|
34
36
|
# max_matches, morphology, charset_type, charset_table, ignore_chars,
|
35
|
-
# html_strip, html_remove_elements, delayed_job_priority
|
37
|
+
# html_strip, html_remove_elements, delayed_job_priority,
|
38
|
+
# searchd_binary_name, indexer_binary_name.
|
36
39
|
#
|
37
40
|
# I think you've got the idea.
|
38
41
|
#
|
@@ -60,7 +63,7 @@ module ThinkingSphinx
|
|
60
63
|
attr_accessor :config_file, :searchd_log_file, :query_log_file,
|
61
64
|
:pid_file, :searchd_file_path, :address, :port, :allow_star,
|
62
65
|
:database_yml_file, :app_root, :bin_path, :model_directories,
|
63
|
-
:delayed_job_priority
|
66
|
+
:delayed_job_priority, :searchd_binary_name, :indexer_binary_name
|
64
67
|
|
65
68
|
attr_accessor :source_options, :index_options
|
66
69
|
|
@@ -107,6 +110,9 @@ module ThinkingSphinx
|
|
107
110
|
self.index_options = {
|
108
111
|
:charset_type => "utf-8"
|
109
112
|
}
|
113
|
+
|
114
|
+
self.searchd_binary_name = "searchd"
|
115
|
+
self.indexer_binary_name = "indexer"
|
110
116
|
|
111
117
|
parse_config
|
112
118
|
|
@@ -18,8 +18,8 @@ module ThinkingSphinx
|
|
18
18
|
config = ThinkingSphinx::Configuration.instance
|
19
19
|
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
20
20
|
|
21
|
-
output = `#{config.bin_path}
|
22
|
-
output += `#{config.bin_path}
|
21
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
22
|
+
output += `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} --merge #{core_index_name model} #{delta_index_name model} --merge-dst-range sphinx_deleted 0 0`
|
23
23
|
puts output unless ThinkingSphinx.suppress_delta_output?
|
24
24
|
|
25
25
|
true
|
@@ -17,7 +17,7 @@ module ThinkingSphinx
|
|
17
17
|
client = Riddle::Client.new config.address, config.port
|
18
18
|
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
19
19
|
|
20
|
-
output = `#{config.bin_path}
|
20
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
21
21
|
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
22
22
|
|
23
23
|
client.update(
|
@@ -14,7 +14,7 @@ module ThinkingSphinx
|
|
14
14
|
config = ThinkingSphinx::Configuration.instance
|
15
15
|
client = Riddle::Client.new config.address, config.port
|
16
16
|
|
17
|
-
output = `#{config.bin_path}
|
17
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} --rotate #{index}`
|
18
18
|
puts output unless ThinkingSphinx.suppress_delta_output?
|
19
19
|
|
20
20
|
true
|
@@ -642,11 +642,11 @@ module ThinkingSphinx
|
|
642
642
|
}.flatten : []
|
643
643
|
|
644
644
|
lat_attr = klass ? klass.sphinx_indexes.collect { |index|
|
645
|
-
index.
|
645
|
+
index.local_options[:latitude_attr]
|
646
646
|
}.compact.first : nil
|
647
647
|
|
648
648
|
lon_attr = klass ? klass.sphinx_indexes.collect { |index|
|
649
|
-
index.
|
649
|
+
index.local_options[:longitude_attr]
|
650
650
|
}.compact.first : nil
|
651
651
|
|
652
652
|
lat_attr = options[:latitude_attr] if options[:latitude_attr]
|
@@ -30,7 +30,7 @@ namespace :thinking_sphinx do
|
|
30
30
|
|
31
31
|
Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
|
32
32
|
|
33
|
-
system! "#{config.bin_path}
|
33
|
+
system! "#{config.bin_path}#{config.searchd_binary_name} --pidfile --config #{config.config_file}"
|
34
34
|
|
35
35
|
sleep(2)
|
36
36
|
|
@@ -46,7 +46,7 @@ namespace :thinking_sphinx do
|
|
46
46
|
raise RuntimeError, "searchd is not running." unless sphinx_running?
|
47
47
|
config = ThinkingSphinx::Configuration.instance
|
48
48
|
pid = sphinx_pid
|
49
|
-
system! "#{config.bin_path}
|
49
|
+
system! "#{config.bin_path}#{config.searchd_binary_name} --stop --config #{config.config_file}"
|
50
50
|
puts "Stopped search daemon (pid #{pid})."
|
51
51
|
end
|
52
52
|
|
@@ -71,7 +71,7 @@ namespace :thinking_sphinx do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
FileUtils.mkdir_p config.searchd_file_path
|
74
|
-
cmd = "#{config.bin_path}
|
74
|
+
cmd = "#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} --all"
|
75
75
|
cmd << " --rotate" if sphinx_running?
|
76
76
|
|
77
77
|
system! cmd
|
@@ -159,4 +159,4 @@ You can set the path to your indexer and searchd binaries using the bin_path pro
|
|
159
159
|
bin_path: '/usr/local/bin'
|
160
160
|
SYSTEM_CALL_FAILED
|
161
161
|
end
|
162
|
-
end
|
162
|
+
end
|
@@ -321,6 +321,26 @@ describe ThinkingSphinx::Attribute do
|
|
321
321
|
end
|
322
322
|
end
|
323
323
|
|
324
|
+
describe "MVA via two has-many associations with a ranged source query" do
|
325
|
+
before :each do
|
326
|
+
@index = ThinkingSphinx::Index.new(Alpha)
|
327
|
+
@source = ThinkingSphinx::Source.new(@index)
|
328
|
+
@attribute = ThinkingSphinx::Attribute.new(@source,
|
329
|
+
[ThinkingSphinx::Index::FauxColumn.new(:betas, :gammas, :value)],
|
330
|
+
:as => :gamma_values, :source => :ranged_query
|
331
|
+
)
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should use a ranged query" do
|
335
|
+
@attribute.type_to_config.should == :sql_attr_multi
|
336
|
+
|
337
|
+
declaration, query, range_query = @attribute.config_value.split('; ')
|
338
|
+
declaration.should == "uint gamma_values from ranged-query"
|
339
|
+
query.should == "SELECT `betas`.`alpha_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `gammas`.`value` AS `gamma_values` FROM `betas` LEFT OUTER JOIN `gammas` ON gammas.beta_id = betas.id WHERE `betas`.`alpha_id` >= $start AND `betas`.`alpha_id` <= $end"
|
340
|
+
range_query.should == "SELECT MIN(`betas`.`alpha_id`), MAX(`betas`.`alpha_id`) FROM `betas`"
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
324
344
|
describe "with custom queries" do
|
325
345
|
before :each do
|
326
346
|
index = CricketTeam.sphinx_indexes.first
|
@@ -12,7 +12,7 @@ describe ThinkingSphinx::Configuration do
|
|
12
12
|
unless defined?(Merb)
|
13
13
|
module ::Merb; end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
ThinkingSphinx::Configuration.stub_method(:defined? => true)
|
17
17
|
Merb.stub!(:environment => "merb_production")
|
18
18
|
ThinkingSphinx::Configuration.environment.should == "merb_production"
|
@@ -48,7 +48,9 @@ describe ThinkingSphinx::Configuration do
|
|
48
48
|
"morphology" => "stem_ru",
|
49
49
|
"charset_type" => "latin1",
|
50
50
|
"charset_table" => "table",
|
51
|
-
"ignore_chars" => "e"
|
51
|
+
"ignore_chars" => "e",
|
52
|
+
"searchd_binary_name" => "sphinx-searchd",
|
53
|
+
"indexer_binary_name" => "sphinx-indexer"
|
52
54
|
}
|
53
55
|
}
|
54
56
|
|
@@ -62,7 +64,7 @@ describe ThinkingSphinx::Configuration do
|
|
62
64
|
config.send(:parse_config)
|
63
65
|
|
64
66
|
%w(config_file searchd_log_file query_log_file pid_file searchd_file_path
|
65
|
-
address port).each do |key|
|
67
|
+
address port searchd_binary_name indexer_binary_name).each do |key|
|
66
68
|
config.send(key).should == @settings["development"][key]
|
67
69
|
end
|
68
70
|
end
|
@@ -217,4 +219,4 @@ describe ThinkingSphinx::Configuration do
|
|
217
219
|
}
|
218
220
|
file.should_not match(/index alpha_core\s+\{\s+[^\}]*prefix_fields\s+=[^\}]*\}/m)
|
219
221
|
end
|
220
|
-
end
|
222
|
+
end
|
@@ -51,6 +51,22 @@ describe ThinkingSphinx do
|
|
51
51
|
ThinkingSphinx.updates_enabled?.should be_true
|
52
52
|
end
|
53
53
|
|
54
|
+
it "should always say Sphinx is running if flagged as being on a remote machine" do
|
55
|
+
ThinkingSphinx.remote_sphinx = true
|
56
|
+
ThinkingSphinx.stub_method(:sphinx_running_by_pid? => false)
|
57
|
+
|
58
|
+
ThinkingSphinx.sphinx_running?.should be_true
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should actually pay attention to Sphinx if not on a remote machine" do
|
62
|
+
ThinkingSphinx.remote_sphinx = false
|
63
|
+
ThinkingSphinx.stub_method(:sphinx_running_by_pid? => false)
|
64
|
+
ThinkingSphinx.sphinx_running?.should be_false
|
65
|
+
|
66
|
+
ThinkingSphinx.stub_method(:sphinx_running_by_pid? => true)
|
67
|
+
ThinkingSphinx.sphinx_running?.should be_true
|
68
|
+
end
|
69
|
+
|
54
70
|
describe "use_group_by_shortcut? method" do
|
55
71
|
before :each do
|
56
72
|
adapter = defined?(JRUBY_VERSION) ? :JdbcAdapter : :MysqlAdapter
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freelancing-god-thinking-sphinx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-22 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|