freelancing-god-thinking-sphinx 1.1.1 → 1.1.2
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 +5 -0
- data/lib/thinking_sphinx.rb +7 -9
- data/lib/thinking_sphinx/active_record/delta.rb +11 -3
- data/lib/thinking_sphinx/attribute.rb +30 -6
- data/lib/thinking_sphinx/configuration.rb +21 -14
- data/lib/thinking_sphinx/deltas.rb +3 -0
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +61 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +11 -2
- data/lib/thinking_sphinx/index.rb +7 -4
- data/lib/thinking_sphinx/rails_additions.rb +12 -0
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +1 -1
- data/tasks/thinking_sphinx_tasks.rb +24 -12
- data/vendor/riddle/lib/riddle/controller.rb +1 -1
- metadata +3 -2
data/README
CHANGED
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -31,7 +31,7 @@ module ThinkingSphinx
|
|
|
31
31
|
module Version #:nodoc:
|
|
32
32
|
Major = 1
|
|
33
33
|
Minor = 1
|
|
34
|
-
Tiny =
|
|
34
|
+
Tiny = 2
|
|
35
35
|
|
|
36
36
|
String = [Major, Minor, Tiny].join('.')
|
|
37
37
|
end
|
|
@@ -131,13 +131,11 @@ module ThinkingSphinx
|
|
|
131
131
|
end
|
|
132
132
|
|
|
133
133
|
def self.sphinx_running?
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
false
|
|
141
|
-
end
|
|
134
|
+
!!sphinx_pid
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.sphinx_pid
|
|
138
|
+
pid_file = ThinkingSphinx::Configuration.instance.pid_file
|
|
139
|
+
`cat #{pid_file}`[/\d+/] if File.exists?(pid_file)
|
|
142
140
|
end
|
|
143
141
|
end
|
|
@@ -42,7 +42,11 @@ module ThinkingSphinx
|
|
|
42
42
|
# if running in the test environment.
|
|
43
43
|
#
|
|
44
44
|
def index_delta(instance = nil)
|
|
45
|
-
|
|
45
|
+
delta_object.index(self, instance)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def delta_object
|
|
49
|
+
self.sphinx_indexes.first.delta_object
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
|
|
@@ -50,14 +54,18 @@ module ThinkingSphinx
|
|
|
50
54
|
|
|
51
55
|
# Set the delta value for the model to be true.
|
|
52
56
|
def toggle_delta
|
|
53
|
-
self.class.
|
|
57
|
+
self.class.delta_object.toggle(self) if should_toggle_delta?
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
# Build the delta index for the related model. This won't be called
|
|
57
61
|
# if running in the test environment.
|
|
58
62
|
#
|
|
59
63
|
def index_delta
|
|
60
|
-
self.class.index_delta(self)
|
|
64
|
+
self.class.index_delta(self) if self.class.delta_object.toggled(self)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def should_toggle_delta?
|
|
68
|
+
!self.respond_to?(:changed?) || self.changed? || self.new_record?
|
|
61
69
|
end
|
|
62
70
|
end
|
|
63
71
|
end
|
|
@@ -175,7 +175,7 @@ module ThinkingSphinx
|
|
|
175
175
|
when "ActiveRecord::ConnectionAdapters::MysqlAdapter"
|
|
176
176
|
"UNIX_TIMESTAMP(#{clause})"
|
|
177
177
|
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
|
178
|
-
|
|
178
|
+
"cast(extract(epoch from #{clause}) as int)"
|
|
179
179
|
else
|
|
180
180
|
clause
|
|
181
181
|
end
|
|
@@ -263,11 +263,7 @@ module ThinkingSphinx
|
|
|
263
263
|
when @associations.values.flatten.length > 1
|
|
264
264
|
:string
|
|
265
265
|
else
|
|
266
|
-
|
|
267
|
-
@associations.values.flatten.first.reflection.klass : @model
|
|
268
|
-
klass.columns.detect { |col|
|
|
269
|
-
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
270
|
-
}.type
|
|
266
|
+
translated_type_from_database
|
|
271
267
|
end
|
|
272
268
|
end
|
|
273
269
|
|
|
@@ -281,5 +277,33 @@ module ThinkingSphinx
|
|
|
281
277
|
}
|
|
282
278
|
}
|
|
283
279
|
end
|
|
280
|
+
|
|
281
|
+
def type_from_database
|
|
282
|
+
klass = @associations.values.flatten.first ?
|
|
283
|
+
@associations.values.flatten.first.reflection.klass : @model
|
|
284
|
+
|
|
285
|
+
klass.columns.detect { |col|
|
|
286
|
+
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
287
|
+
}.type
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def translated_type_from_database
|
|
291
|
+
case type_from_db = type_from_database
|
|
292
|
+
when :datetime, :string, :float, :boolean, :integer
|
|
293
|
+
type_from_db
|
|
294
|
+
when :decimal
|
|
295
|
+
:float
|
|
296
|
+
when :timestamp, :date
|
|
297
|
+
:datetime
|
|
298
|
+
else
|
|
299
|
+
raise <<-MESSAGE
|
|
300
|
+
|
|
301
|
+
Cannot automatically map column type #{type_from_db} to an equivalent Sphinx
|
|
302
|
+
type (integer, float, boolean, datetime, string as ordinal). You could try to
|
|
303
|
+
explicitly convert the column's value in your define_index block:
|
|
304
|
+
has "CAST(column AS INT)", :type => :integer, :as => :column
|
|
305
|
+
MESSAGE
|
|
306
|
+
end
|
|
307
|
+
end
|
|
284
308
|
end
|
|
285
309
|
end
|
|
@@ -55,7 +55,7 @@ module ThinkingSphinx
|
|
|
55
55
|
|
|
56
56
|
attr_accessor :config_file, :searchd_log_file, :query_log_file,
|
|
57
57
|
:pid_file, :searchd_file_path, :address, :port, :allow_star,
|
|
58
|
-
:database_yml_file, :app_root, :bin_path
|
|
58
|
+
:database_yml_file, :app_root, :bin_path, :model_directories
|
|
59
59
|
|
|
60
60
|
attr_accessor :source_options, :index_options
|
|
61
61
|
|
|
@@ -85,6 +85,7 @@ module ThinkingSphinx
|
|
|
85
85
|
self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
|
|
86
86
|
self.allow_star = false
|
|
87
87
|
self.bin_path = ""
|
|
88
|
+
self.model_directories = ["#{app_root}/app/models/"]
|
|
88
89
|
|
|
89
90
|
self.source_options = {}
|
|
90
91
|
self.index_options = {
|
|
@@ -135,21 +136,22 @@ module ThinkingSphinx
|
|
|
135
136
|
# messy dependencies issues).
|
|
136
137
|
#
|
|
137
138
|
def load_models
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
self.model_directories.each do |base|
|
|
140
|
+
Dir["#{base}**/*.rb"].each do |file|
|
|
141
|
+
model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
next if model_name.nil?
|
|
144
|
+
next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
|
|
145
|
+
model.name == model_name
|
|
146
|
+
}
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
begin
|
|
149
|
+
model_name.camelize.constantize
|
|
150
|
+
rescue LoadError
|
|
151
|
+
model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
|
|
152
|
+
rescue NameError
|
|
153
|
+
next
|
|
154
|
+
end
|
|
153
155
|
end
|
|
154
156
|
end
|
|
155
157
|
end
|
|
@@ -240,6 +242,11 @@ module ThinkingSphinx
|
|
|
240
242
|
end unless conf.nil?
|
|
241
243
|
|
|
242
244
|
self.bin_path += '/' unless self.bin_path.blank?
|
|
245
|
+
|
|
246
|
+
if self.allow_star
|
|
247
|
+
self.index_options[:enable_star] = true
|
|
248
|
+
self.index_options[:min_prefix_len] = 1
|
|
249
|
+
end
|
|
243
250
|
end
|
|
244
251
|
|
|
245
252
|
def set_sphinx_setting(object, key, value, allowed = {})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'thinking_sphinx/deltas/default_delta'
|
|
2
2
|
require 'thinking_sphinx/deltas/delayed_delta'
|
|
3
|
+
require 'thinking_sphinx/deltas/datetime_delta'
|
|
3
4
|
|
|
4
5
|
module ThinkingSphinx
|
|
5
6
|
module Deltas
|
|
@@ -9,6 +10,8 @@ module ThinkingSphinx
|
|
|
9
10
|
DefaultDelta.new index, options
|
|
10
11
|
when :delayed
|
|
11
12
|
DelayedDelta.new index, options
|
|
13
|
+
when :datetime
|
|
14
|
+
DatetimeDelta.new index, options
|
|
12
15
|
when FalseClass, nil
|
|
13
16
|
nil
|
|
14
17
|
else
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module ThinkingSphinx
|
|
2
|
+
module Deltas
|
|
3
|
+
class DatetimeDelta < ThinkingSphinx::Deltas::DefaultDelta
|
|
4
|
+
attr_accessor :column, :threshold
|
|
5
|
+
|
|
6
|
+
def initialize(index, options)
|
|
7
|
+
@index = index
|
|
8
|
+
@column = options.delete(:delta_column) || :updated_at
|
|
9
|
+
@threshold = options.delete(:threshold) || 1.day
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def index(model, instance = nil)
|
|
13
|
+
# do nothing
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def delayed_index(model)
|
|
18
|
+
config = ThinkingSphinx::Configuration.instance
|
|
19
|
+
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
|
20
|
+
|
|
21
|
+
output = `#{config.bin_path}indexer --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
|
22
|
+
output += `#{config.bin_path}indexer --config #{config.config_file} #{rotate} --merge #{core_index_name model} #{delta_index_name model} --merge-dst-range sphinx_deleted 0 0`
|
|
23
|
+
puts output unless ThinkingSphinx.suppress_delta_output?
|
|
24
|
+
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def toggle(instance)
|
|
29
|
+
# do nothing
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def toggled(instance)
|
|
33
|
+
instance.send(@column) > @threshold.ago
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def reset_query(model)
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def clause(model, toggled)
|
|
41
|
+
if toggled
|
|
42
|
+
"#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
|
|
43
|
+
" > #{time_difference}"
|
|
44
|
+
else
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def time_difference
|
|
50
|
+
case @index.adapter
|
|
51
|
+
when :mysql
|
|
52
|
+
"DATE_SUB(NOW(), INTERVAL #{@threshold} SECOND)"
|
|
53
|
+
when :postgres
|
|
54
|
+
"current_timestamp - interval '#{@threshold} seconds'"
|
|
55
|
+
else
|
|
56
|
+
raise "Unknown Database Adapter"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -5,7 +5,7 @@ module ThinkingSphinx
|
|
|
5
5
|
|
|
6
6
|
def initialize(index, options)
|
|
7
7
|
@index = index
|
|
8
|
-
@column = options.delete(:
|
|
8
|
+
@column = options.delete(:delta_column) || :delta
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def index(model, instance = nil)
|
|
@@ -31,6 +31,15 @@ module ThinkingSphinx
|
|
|
31
31
|
instance.delta = true
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def toggled(instance)
|
|
35
|
+
instance.delta
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def reset_query(model)
|
|
39
|
+
"UPDATE #{model.quoted_table_name} SET " +
|
|
40
|
+
"#{@index.quote_column(@column.to_s)} = #{@index.db_boolean(false)}"
|
|
41
|
+
end
|
|
42
|
+
|
|
34
43
|
def clause(model, toggled)
|
|
35
44
|
"#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
|
|
36
45
|
" = #{@index.db_boolean(toggled)}"
|
|
@@ -44,7 +53,7 @@ module ThinkingSphinx
|
|
|
44
53
|
|
|
45
54
|
def delta_index_name(model)
|
|
46
55
|
"#{model.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_delta"
|
|
47
|
-
end
|
|
56
|
+
end
|
|
48
57
|
end
|
|
49
58
|
end
|
|
50
59
|
end
|
|
@@ -126,7 +126,7 @@ module ThinkingSphinx
|
|
|
126
126
|
assocs = all_associations
|
|
127
127
|
|
|
128
128
|
where_clause = ""
|
|
129
|
-
if self.delta?
|
|
129
|
+
if self.delta? && !@delta_object.clause(@model, options[:delta]).blank?
|
|
130
130
|
where_clause << " AND #{@delta_object.clause(@model, options[:delta])}"
|
|
131
131
|
end
|
|
132
132
|
unless @conditions.empty?
|
|
@@ -190,7 +190,10 @@ GROUP BY #{ (
|
|
|
190
190
|
|
|
191
191
|
sql = "SELECT #{min_statement}, #{max_statement} " +
|
|
192
192
|
"FROM #{@model.quoted_table_name} "
|
|
193
|
-
|
|
193
|
+
if self.delta? && !@delta_object.clause(@model, options[:delta]).blank?
|
|
194
|
+
sql << "WHERE #{@delta_object.clause(@model, options[:delta])}"
|
|
195
|
+
end
|
|
196
|
+
|
|
194
197
|
sql
|
|
195
198
|
end
|
|
196
199
|
|
|
@@ -436,8 +439,8 @@ GROUP BY #{ (
|
|
|
436
439
|
end
|
|
437
440
|
|
|
438
441
|
def sql_query_pre_for_core
|
|
439
|
-
if self.delta?
|
|
440
|
-
[
|
|
442
|
+
if self.delta? && !@delta_object.reset_query(@model).blank?
|
|
443
|
+
[@delta_object.reset_query(@model)]
|
|
441
444
|
else
|
|
442
445
|
[]
|
|
443
446
|
end
|
|
@@ -29,6 +29,18 @@ Array.send(
|
|
|
29
29
|
:include, ThinkingSphinx::ArrayExtractOptions
|
|
30
30
|
) unless Array.instance_methods.include?("extract_options!")
|
|
31
31
|
|
|
32
|
+
module ThinkingSphinx
|
|
33
|
+
module AbstractQuotedTableName
|
|
34
|
+
def quote_table_name(name)
|
|
35
|
+
quote_column_name(name)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(
|
|
41
|
+
:include, ThinkingSphinx::AbstractQuotedTableName
|
|
42
|
+
) unless ActiveRecord::ConnectionAdapters::AbstractAdapter.instance_methods.include?("quote_table_name")
|
|
43
|
+
|
|
32
44
|
module ThinkingSphinx
|
|
33
45
|
module MysqlQuotedTableName
|
|
34
46
|
def quote_table_name(name) #:nodoc:
|
|
@@ -72,7 +72,7 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
|
|
|
72
72
|
before :each do
|
|
73
73
|
ThinkingSphinx::Configuration.stub_method(:environment => "spec")
|
|
74
74
|
ThinkingSphinx.stub_method(:deltas_enabled? => true, :sphinx_running? => true)
|
|
75
|
-
Person.
|
|
75
|
+
Person.delta_object.stub_methods(:` => "", :toggled => true)
|
|
76
76
|
|
|
77
77
|
@person = Person.new
|
|
78
78
|
@person.stub_method(
|
|
@@ -37,8 +37,9 @@ namespace :thinking_sphinx do
|
|
|
37
37
|
desc "Stop Sphinx using Thinking Sphinx's settings"
|
|
38
38
|
task :stop => :app_env do
|
|
39
39
|
raise RuntimeError, "searchd is not running." unless sphinx_running?
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
config = ThinkingSphinx::Configuration.instance
|
|
41
|
+
pid = sphinx_pid
|
|
42
|
+
system "searchd --stop --config #{config.config_file}"
|
|
42
43
|
puts "Stopped search daemon (pid #{pid})."
|
|
43
44
|
end
|
|
44
45
|
|
|
@@ -69,8 +70,22 @@ namespace :thinking_sphinx do
|
|
|
69
70
|
system cmd
|
|
70
71
|
end
|
|
71
72
|
|
|
73
|
+
namespace :index do
|
|
74
|
+
task :delta => :app_env do
|
|
75
|
+
ThinkingSphinx.indexed_models.select { |model|
|
|
76
|
+
model.constantize.sphinx_indexes.any? { |index| index.delta? }
|
|
77
|
+
}.each do |model|
|
|
78
|
+
model.constantize.sphinx_indexes.select { |index|
|
|
79
|
+
index.delta? && index.delta_object.respond_to?(:delayed_index)
|
|
80
|
+
}.each { |index|
|
|
81
|
+
index.delta_object.delayed_index(index.model)
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
72
87
|
desc "Process stored delta index requests"
|
|
73
|
-
task :
|
|
88
|
+
task :delayed_delta => :app_env do
|
|
74
89
|
require 'delayed/worker'
|
|
75
90
|
|
|
76
91
|
Delayed::Worker.new(
|
|
@@ -90,6 +105,9 @@ namespace :ts do
|
|
|
90
105
|
desc "Index data for Sphinx using Thinking Sphinx's settings"
|
|
91
106
|
task :in => "thinking_sphinx:index"
|
|
92
107
|
desc "Index data for Sphinx using Thinking Sphinx's settings"
|
|
108
|
+
namespace :in do
|
|
109
|
+
task :delta => "thinking_sphinx:index:delta"
|
|
110
|
+
end
|
|
93
111
|
task :index => "thinking_sphinx:index"
|
|
94
112
|
desc "Restart Sphinx"
|
|
95
113
|
task :restart => "thinking_sphinx:restart"
|
|
@@ -98,19 +116,13 @@ namespace :ts do
|
|
|
98
116
|
desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
|
|
99
117
|
task :config => "thinking_sphinx:configure"
|
|
100
118
|
desc "Process stored delta index requests"
|
|
101
|
-
task :
|
|
119
|
+
task :dd => "thinking_sphinx:delayed_delta"
|
|
102
120
|
end
|
|
103
121
|
|
|
104
122
|
def sphinx_pid
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if File.exists?(config.pid_file)
|
|
108
|
-
`cat #{config.pid_file}`[/\d+/]
|
|
109
|
-
else
|
|
110
|
-
nil
|
|
111
|
-
end
|
|
123
|
+
ThinkingSphinx.sphinx_pid
|
|
112
124
|
end
|
|
113
125
|
|
|
114
126
|
def sphinx_running?
|
|
115
|
-
|
|
127
|
+
ThinkingSphinx.sphinx_running?
|
|
116
128
|
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.2
|
|
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-01-
|
|
12
|
+
date: 2009-01-08 00:00:00 -08:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -33,6 +33,7 @@ files:
|
|
|
33
33
|
- lib/thinking_sphinx/attribute.rb
|
|
34
34
|
- lib/thinking_sphinx/collection.rb
|
|
35
35
|
- lib/thinking_sphinx/configuration.rb
|
|
36
|
+
- lib/thinking_sphinx/deltas/datetime_delta.rb
|
|
36
37
|
- lib/thinking_sphinx/deltas/default_delta.rb
|
|
37
38
|
- lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb
|
|
38
39
|
- lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb
|