freelancing-god-thinking-sphinx 1.1.16 → 1.1.17
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/README.textile +1 -0
- data/lib/thinking_sphinx.rb +1 -1
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +6 -1
- data/lib/thinking_sphinx/attribute.rb +2 -2
- data/lib/thinking_sphinx/configuration.rb +13 -4
- data/lib/thinking_sphinx/search.rb +15 -9
- data/lib/thinking_sphinx/search/facets.rb +6 -1
- data/lib/thinking_sphinx/source.rb +2 -2
- data/lib/thinking_sphinx/tasks.rb +29 -6
- data/spec/unit/thinking_sphinx/configuration_spec.rb +10 -1
- data/spec/unit/thinking_sphinx/index/builder_spec.rb +6 -2
- data/spec/unit/thinking_sphinx/search_spec.rb +15 -2
- data/spec/unit/thinking_sphinx/source_spec.rb +11 -2
- metadata +2 -2
data/README.textile
CHANGED
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -11,7 +11,12 @@ module ThinkingSphinx
|
|
|
11
11
|
|
|
12
12
|
def concatenate(clause, separator = ' ')
|
|
13
13
|
clause.split(', ').collect { |field|
|
|
14
|
-
|
|
14
|
+
case field
|
|
15
|
+
when /COALESCE/, "'')"
|
|
16
|
+
field
|
|
17
|
+
else
|
|
18
|
+
"COALESCE(CAST(#{field} as varchar), '')"
|
|
19
|
+
end
|
|
15
20
|
}.join(" || '#{separator}' || ")
|
|
16
21
|
end
|
|
17
22
|
|
|
@@ -89,13 +89,13 @@ module ThinkingSphinx
|
|
|
89
89
|
def to_select_sql
|
|
90
90
|
return nil unless include_as_association?
|
|
91
91
|
|
|
92
|
+
separator = all_ints? || @crc ? ',' : ' '
|
|
93
|
+
|
|
92
94
|
clause = @columns.collect { |column|
|
|
93
95
|
part = column_with_prefix(column)
|
|
94
96
|
type == :string ? adapter.convert_nulls(part) : part
|
|
95
97
|
}.join(', ')
|
|
96
98
|
|
|
97
|
-
separator = all_ints? || @crc ? ',' : ' '
|
|
98
|
-
|
|
99
99
|
clause = adapter.cast_to_datetime(clause) if type == :datetime
|
|
100
100
|
clause = adapter.crc(clause) if @crc
|
|
101
101
|
clause = adapter.concatenate(clause, separator) if concat_ws?
|
|
@@ -71,10 +71,19 @@ module ThinkingSphinx
|
|
|
71
71
|
self.reset
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
def self.configure(&block)
|
|
75
|
+
yield instance
|
|
76
|
+
instance.reset(instance.app_root)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def reset(custom_app_root=nil)
|
|
80
|
+
if custom_app_root
|
|
81
|
+
self.app_root = custom_app_root
|
|
82
|
+
else
|
|
83
|
+
self.app_root = RAILS_ROOT if defined?(RAILS_ROOT)
|
|
84
|
+
self.app_root = Merb.root if defined?(Merb)
|
|
85
|
+
self.app_root ||= app_root
|
|
86
|
+
end
|
|
78
87
|
|
|
79
88
|
@configuration = Riddle::Configuration.new
|
|
80
89
|
@configuration.searchd.address = "127.0.0.1"
|
|
@@ -358,10 +358,8 @@ module ThinkingSphinx
|
|
|
358
358
|
|
|
359
359
|
retry_search_on_stale_index(query, options) do
|
|
360
360
|
results, client = search_results(*(query + [options]))
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
"Sphinx Error: #{results[:error]}"
|
|
364
|
-
) if results[:error]
|
|
361
|
+
|
|
362
|
+
log "Sphinx Error: #{results[:error]}", :error if results[:error]
|
|
365
363
|
|
|
366
364
|
klass = options[:class]
|
|
367
365
|
page = options[:page] ? options[:page].to_i : 1
|
|
@@ -394,9 +392,9 @@ module ThinkingSphinx
|
|
|
394
392
|
options[:without_ids] = Array(options[:without_ids]) | e.ids # Actual exclusion
|
|
395
393
|
|
|
396
394
|
tries = stale_retries_left
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
]
|
|
395
|
+
log "Sphinx Stale Ids (%s %s left): %s" % [
|
|
396
|
+
tries, (tries==1 ? 'try' : 'tries'), stale_ids.join(', ')
|
|
397
|
+
]
|
|
400
398
|
|
|
401
399
|
retry
|
|
402
400
|
end
|
|
@@ -465,9 +463,12 @@ module ThinkingSphinx
|
|
|
465
463
|
client.offset = (page - 1) * client.limit
|
|
466
464
|
|
|
467
465
|
begin
|
|
468
|
-
|
|
466
|
+
log "Sphinx: #{query}"
|
|
469
467
|
results = client.query query
|
|
470
|
-
|
|
468
|
+
log "Sphinx Result:"
|
|
469
|
+
log results[:matches].collect { |m|
|
|
470
|
+
m[:attributes]["sphinx_internal_id"]
|
|
471
|
+
}.inspect
|
|
471
472
|
rescue Errno::ECONNREFUSED => err
|
|
472
473
|
raise ThinkingSphinx::ConnectionError, "Connection to Sphinx Daemon (searchd) failed."
|
|
473
474
|
end
|
|
@@ -706,6 +707,11 @@ module ThinkingSphinx
|
|
|
706
707
|
|
|
707
708
|
string
|
|
708
709
|
end
|
|
710
|
+
|
|
711
|
+
def log(message, method = :debug)
|
|
712
|
+
return if ::ActiveRecord::Base.logger.nil?
|
|
713
|
+
::ActiveRecord::Base.logger.send method, message
|
|
714
|
+
end
|
|
709
715
|
end
|
|
710
716
|
end
|
|
711
717
|
end
|
|
@@ -22,7 +22,12 @@ module ThinkingSphinx
|
|
|
22
22
|
hash = ThinkingSphinx::FacetCollection.new args + [options]
|
|
23
23
|
options = options.clone.merge! facet_query_options
|
|
24
24
|
|
|
25
|
-
klass.sphinx_facets
|
|
25
|
+
facets = klass.sphinx_facets
|
|
26
|
+
facets = Array(options.delete(:facets)).collect { |name|
|
|
27
|
+
klass.sphinx_facets.detect { |facet| facet.name.to_s == name.to_s }
|
|
28
|
+
}.compact if options[:facets]
|
|
29
|
+
|
|
30
|
+
facets.inject(hash) do |hash, facet|
|
|
26
31
|
unless facet.name == :class && !options[:class_facet]
|
|
27
32
|
options[:group_by] = facet.attribute_name
|
|
28
33
|
hash.add_from_results facet, search(*(args + [options]))
|
|
@@ -102,8 +102,8 @@ module ThinkingSphinx
|
|
|
102
102
|
|
|
103
103
|
source.sql_query_pre += send(!delta ? :sql_query_pre_for_core : :sql_query_pre_for_delta)
|
|
104
104
|
|
|
105
|
-
if @
|
|
106
|
-
source.sql_query_pre << "SET SESSION group_concat_max_len = #{@
|
|
105
|
+
if @index.local_options[:group_concat_max_len]
|
|
106
|
+
source.sql_query_pre << "SET SESSION group_concat_max_len = #{@index.local_options[:group_concat_max_len]}"
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
source.sql_query_pre += [adapter.utf8_query_pre].compact if utf8?
|
|
@@ -26,9 +26,7 @@ namespace :thinking_sphinx do
|
|
|
26
26
|
|
|
27
27
|
Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
puts cmd
|
|
31
|
-
system cmd
|
|
29
|
+
system! "#{config.bin_path}searchd --pidfile --config #{config.config_file}"
|
|
32
30
|
|
|
33
31
|
sleep(2)
|
|
34
32
|
|
|
@@ -44,7 +42,7 @@ namespace :thinking_sphinx do
|
|
|
44
42
|
raise RuntimeError, "searchd is not running." unless sphinx_running?
|
|
45
43
|
config = ThinkingSphinx::Configuration.instance
|
|
46
44
|
pid = sphinx_pid
|
|
47
|
-
system "#{config.bin_path}searchd --stop --config #{config.config_file}"
|
|
45
|
+
system! "#{config.bin_path}searchd --stop --config #{config.config_file}"
|
|
48
46
|
puts "Stopped search daemon (pid #{pid})."
|
|
49
47
|
end
|
|
50
48
|
|
|
@@ -71,8 +69,15 @@ namespace :thinking_sphinx do
|
|
|
71
69
|
FileUtils.mkdir_p config.searchd_file_path
|
|
72
70
|
cmd = "#{config.bin_path}indexer --config #{config.config_file} --all"
|
|
73
71
|
cmd << " --rotate" if sphinx_running?
|
|
74
|
-
|
|
75
|
-
system cmd
|
|
72
|
+
|
|
73
|
+
system! cmd
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
|
|
77
|
+
task :rebuild => :app_env do
|
|
78
|
+
Rake::Task["thinking_sphinx:stop"].invoke if sphinx_running?
|
|
79
|
+
Rake::Task["thinking_sphinx:index"].invoke
|
|
80
|
+
Rake::Task["thinking_sphinx:start"].invoke
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
namespace :index do
|
|
@@ -122,6 +127,8 @@ namespace :ts do
|
|
|
122
127
|
task :conf => "thinking_sphinx:configure"
|
|
123
128
|
desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
|
|
124
129
|
task :config => "thinking_sphinx:configure"
|
|
130
|
+
desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
|
|
131
|
+
task :rebuild => "thinking_sphinx:rebuild"
|
|
125
132
|
desc "Process stored delta index requests"
|
|
126
133
|
task :dd => "thinking_sphinx:delayed_delta"
|
|
127
134
|
end
|
|
@@ -133,3 +140,19 @@ end
|
|
|
133
140
|
def sphinx_running?
|
|
134
141
|
ThinkingSphinx.sphinx_running?
|
|
135
142
|
end
|
|
143
|
+
|
|
144
|
+
# a fail-fast, hopefully helpful version of system
|
|
145
|
+
def system!(cmd)
|
|
146
|
+
unless system(cmd)
|
|
147
|
+
raise <<-SYSTEM_CALL_FAILED
|
|
148
|
+
The following command failed:
|
|
149
|
+
#{cmd}
|
|
150
|
+
|
|
151
|
+
This could be caused by a PATH issue in the environment of cron/passenger/etc. Your current PATH:
|
|
152
|
+
#{ENV['PATH']}
|
|
153
|
+
You can set the path to your indexer and searchd binaries using the bin_path property in config/sphinx.yml:
|
|
154
|
+
production:
|
|
155
|
+
bin_path: '/usr/local/bin'
|
|
156
|
+
SYSTEM_CALL_FAILED
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -71,7 +71,16 @@ describe ThinkingSphinx::Configuration do
|
|
|
71
71
|
FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
|
-
|
|
74
|
+
|
|
75
|
+
describe "block configuration" do
|
|
76
|
+
it "should let the user set-up a custom app_root" do
|
|
77
|
+
ThinkingSphinx::Configuration.configure do |config|
|
|
78
|
+
config.app_root = "/here/somewhere"
|
|
79
|
+
end
|
|
80
|
+
ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
75
84
|
describe "initialisation" do
|
|
76
85
|
it "should have a default bin_path of nothing" do
|
|
77
86
|
ThinkingSphinx::Configuration.instance.bin_path.should == ""
|
|
@@ -318,13 +318,17 @@ describe ThinkingSphinx::Index::Builder do
|
|
|
318
318
|
indexes first_name
|
|
319
319
|
|
|
320
320
|
set_property :charset_type => "utf16"
|
|
321
|
+
set_property :group_concat_max_len => 1024
|
|
321
322
|
end
|
|
322
323
|
end
|
|
323
324
|
|
|
324
|
-
it "should store the setting for the index" do
|
|
325
|
-
@index.local_options.length.should == 1
|
|
325
|
+
it "should store the index setting for the index" do
|
|
326
326
|
@index.local_options[:charset_type].should == "utf16"
|
|
327
327
|
end
|
|
328
|
+
|
|
329
|
+
it "should store non-Sphinx settings for the index" do
|
|
330
|
+
@index.local_options[:group_concat_max_len].should == 1024
|
|
331
|
+
end
|
|
328
332
|
end
|
|
329
333
|
|
|
330
334
|
describe "delta options" do
|
|
@@ -99,13 +99,13 @@ describe ThinkingSphinx::Search do
|
|
|
99
99
|
@birthday_results.stub!(:each_with_groupby_and_count).
|
|
100
100
|
and_yield(@person, @person.birthday.to_i, 1)
|
|
101
101
|
|
|
102
|
-
ThinkingSphinx::Search.stub!(:search).and_return(@city_results, @birthday_results)
|
|
103
|
-
|
|
104
102
|
@config = ThinkingSphinx::Configuration.instance
|
|
105
103
|
@config.configuration.searchd.max_matches = 10_000
|
|
106
104
|
end
|
|
107
105
|
|
|
108
106
|
it "should use the system-set max_matches for limit on facet calls" do
|
|
107
|
+
ThinkingSphinx::Search.stub!(:search).and_return(@city_results, @birthday_results)
|
|
108
|
+
|
|
109
109
|
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
110
110
|
options[:max_matches].should == 10_000
|
|
111
111
|
options[:limit].should == 10_000
|
|
@@ -115,6 +115,8 @@ describe ThinkingSphinx::Search do
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
it "should use the default max-matches if there is no explicit setting" do
|
|
118
|
+
ThinkingSphinx::Search.stub!(:search).and_return(@city_results, @birthday_results)
|
|
119
|
+
|
|
118
120
|
@config.configuration.searchd.max_matches = nil
|
|
119
121
|
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
120
122
|
options[:max_matches].should == 1000
|
|
@@ -125,6 +127,8 @@ describe ThinkingSphinx::Search do
|
|
|
125
127
|
end
|
|
126
128
|
|
|
127
129
|
it "should ignore user-provided max_matches and limit on facet calls" do
|
|
130
|
+
ThinkingSphinx::Search.stub!(:search).and_return(@city_results, @birthday_results)
|
|
131
|
+
|
|
128
132
|
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
129
133
|
options[:max_matches].should == 10_000
|
|
130
134
|
options[:limit].should == 10_000
|
|
@@ -137,6 +141,15 @@ describe ThinkingSphinx::Search do
|
|
|
137
141
|
)
|
|
138
142
|
end
|
|
139
143
|
|
|
144
|
+
it "should use explicit facet list if one is provided" do
|
|
145
|
+
ThinkingSphinx::Search.should_receive(:search).once.and_return(@city_results)
|
|
146
|
+
|
|
147
|
+
ThinkingSphinx::Search.facets(
|
|
148
|
+
:facets => ['city'],
|
|
149
|
+
:class => Person
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
|
|
140
153
|
describe "conflicting facets" do
|
|
141
154
|
before :each do
|
|
142
155
|
@index = ThinkingSphinx::Index::Builder.generate(Alpha) do
|
|
@@ -41,6 +41,8 @@ describe ThinkingSphinx::Source do
|
|
|
41
41
|
@source.conditions << "`birthday` <= NOW()"
|
|
42
42
|
@source.groupings << "`first_name`"
|
|
43
43
|
|
|
44
|
+
@index.local_options[:group_concat_max_len] = 1024
|
|
45
|
+
|
|
44
46
|
@riddle = @source.to_riddle_for_core(1, 0)
|
|
45
47
|
end
|
|
46
48
|
|
|
@@ -148,8 +150,15 @@ describe ThinkingSphinx::Source do
|
|
|
148
150
|
end
|
|
149
151
|
|
|
150
152
|
it "should default to just the UTF8 statement" do
|
|
151
|
-
@queries.
|
|
152
|
-
|
|
153
|
+
@queries.detect { |query|
|
|
154
|
+
query == "SET NAMES utf8"
|
|
155
|
+
}.should_not be_nil
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "should set the group_concat_max_len session value for MySQL if requested" do
|
|
159
|
+
@queries.detect { |query|
|
|
160
|
+
query == "SET SESSION group_concat_max_len = 1024"
|
|
161
|
+
}.should_not be_nil
|
|
153
162
|
end
|
|
154
163
|
end
|
|
155
164
|
end
|
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.17
|
|
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-05-
|
|
12
|
+
date: 2009-05-24 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|