thinking-sphinx 1.2.13 → 1.4.0
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 +37 -4
- data/VERSION +1 -0
- data/features/abstract_inheritance.feature +10 -0
- data/features/alternate_primary_key.feature +1 -1
- data/features/attribute_updates.feature +49 -5
- data/features/deleting_instances.feature +3 -0
- data/features/excerpts.feature +8 -0
- data/features/facets.feature +15 -1
- data/features/facets_across_model.feature +2 -2
- data/features/field_sorting.feature +18 -0
- data/features/handling_edits.feature +1 -1
- data/features/searching_across_models.feature +2 -2
- data/features/searching_by_index.feature +40 -0
- data/features/searching_by_model.feature +1 -8
- data/features/sphinx_scopes.feature +33 -0
- data/features/step_definitions/alpha_steps.rb +14 -1
- data/features/step_definitions/beta_steps.rb +1 -1
- data/features/step_definitions/common_steps.rb +21 -2
- data/features/step_definitions/facet_steps.rb +4 -0
- data/features/step_definitions/scope_steps.rb +8 -0
- data/features/step_definitions/search_steps.rb +5 -0
- data/features/step_definitions/sphinx_steps.rb +8 -4
- data/features/sti_searching.feature +5 -0
- data/features/support/env.rb +7 -6
- data/features/{support → thinking_sphinx}/db/fixtures/betas.rb +1 -0
- data/features/{support → thinking_sphinx}/db/fixtures/comments.rb +1 -1
- data/features/{support → thinking_sphinx}/db/fixtures/developers.rb +2 -0
- data/features/thinking_sphinx/db/fixtures/foxes.rb +3 -0
- data/features/thinking_sphinx/db/fixtures/music.rb +4 -0
- data/features/{support → thinking_sphinx}/db/fixtures/people.rb +1 -1
- data/features/{support → thinking_sphinx}/db/fixtures/tags.rb +1 -1
- data/features/{support → thinking_sphinx}/db/migrations/create_alphas.rb +1 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_developers.rb +0 -2
- data/features/thinking_sphinx/db/migrations/create_genres.rb +3 -0
- data/features/thinking_sphinx/db/migrations/create_music.rb +6 -0
- data/features/thinking_sphinx/models/alpha.rb +23 -0
- data/features/thinking_sphinx/models/andrew.rb +17 -0
- data/features/{support → thinking_sphinx}/models/beta.rb +1 -1
- data/features/{support → thinking_sphinx}/models/developer.rb +2 -2
- data/features/{support → thinking_sphinx}/models/extensible_beta.rb +1 -1
- data/features/thinking_sphinx/models/fox.rb +5 -0
- data/features/thinking_sphinx/models/genre.rb +3 -0
- data/features/thinking_sphinx/models/medium.rb +5 -0
- data/features/thinking_sphinx/models/music.rb +8 -0
- data/features/{support → thinking_sphinx}/models/person.rb +2 -1
- data/features/{support → thinking_sphinx}/models/post.rb +2 -1
- data/lib/cucumber/thinking_sphinx/external_world.rb +12 -0
- data/lib/cucumber/thinking_sphinx/internal_world.rb +13 -11
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +17 -15
- data/lib/thinking_sphinx/active_record/delta.rb +0 -26
- data/lib/thinking_sphinx/active_record/has_many_association.rb +34 -11
- data/lib/thinking_sphinx/active_record/scopes.rb +46 -3
- data/lib/thinking_sphinx/active_record.rb +271 -193
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +45 -9
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +5 -1
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -1
- data/lib/thinking_sphinx/attribute.rb +67 -23
- data/lib/thinking_sphinx/auto_version.rb +24 -0
- data/lib/thinking_sphinx/bundled_search.rb +44 -0
- data/lib/thinking_sphinx/class_facet.rb +3 -2
- data/lib/thinking_sphinx/configuration.rb +78 -64
- data/lib/thinking_sphinx/context.rb +76 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +14 -20
- data/lib/thinking_sphinx/deltas.rb +0 -2
- data/lib/thinking_sphinx/deploy/capistrano.rb +1 -1
- data/lib/thinking_sphinx/excerpter.rb +1 -1
- data/lib/thinking_sphinx/facet.rb +6 -5
- data/lib/thinking_sphinx/facet_search.rb +54 -24
- data/lib/thinking_sphinx/field.rb +2 -4
- data/lib/thinking_sphinx/index/builder.rb +36 -20
- data/lib/thinking_sphinx/index/faux_column.rb +8 -0
- data/lib/thinking_sphinx/index.rb +77 -19
- data/lib/thinking_sphinx/join.rb +37 -0
- data/lib/thinking_sphinx/property.rb +9 -2
- data/lib/thinking_sphinx/rails_additions.rb +4 -4
- data/lib/thinking_sphinx/search.rb +212 -66
- data/lib/thinking_sphinx/search_methods.rb +22 -4
- data/lib/thinking_sphinx/source/internal_properties.rb +2 -2
- data/lib/thinking_sphinx/source/sql.rb +5 -3
- data/lib/thinking_sphinx/source.rb +21 -12
- data/lib/thinking_sphinx/tasks.rb +26 -58
- data/lib/thinking_sphinx/test.rb +55 -0
- data/lib/thinking_sphinx.rb +70 -38
- data/rails/init.rb +4 -2
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/delta_spec.rb +6 -8
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/has_many_association_spec.rb +26 -3
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +176 -0
- data/spec/thinking_sphinx/active_record_spec.rb +618 -0
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +134 -0
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/association_spec.rb +1 -1
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/attribute_spec.rb +87 -46
- data/spec/thinking_sphinx/auto_version_spec.rb +47 -0
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/configuration_spec.rb +73 -63
- data/spec/thinking_sphinx/context_spec.rb +127 -0
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/array_spec.rb +1 -1
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/string_spec.rb +1 -1
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/excerpter_spec.rb +1 -9
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_search_spec.rb +76 -82
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_spec.rb +5 -5
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/field_spec.rb +1 -42
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/builder_spec.rb +71 -31
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/faux_column_spec.rb +8 -2
- data/spec/thinking_sphinx/index_spec.rb +183 -0
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/rails_additions_spec.rb +5 -5
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_methods_spec.rb +5 -1
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_spec.rb +183 -31
- data/spec/{lib/thinking_sphinx → thinking_sphinx}/source_spec.rb +18 -2
- data/spec/thinking_sphinx/test_spec.rb +20 -0
- data/spec/thinking_sphinx_spec.rb +204 -0
- data/tasks/distribution.rb +7 -26
- data/tasks/testing.rb +32 -20
- metadata +488 -147
- data/VERSION.yml +0 -5
- data/features/datetime_deltas.feature +0 -66
- data/features/delayed_delta_indexing.feature +0 -37
- data/features/step_definitions/datetime_delta_steps.rb +0 -15
- data/features/step_definitions/delayed_delta_indexing_steps.rb +0 -7
- data/features/support/database.yml +0 -5
- data/features/support/db/active_record.rb +0 -40
- data/features/support/db/database.yml +0 -5
- data/features/support/db/fixtures/delayed_betas.rb +0 -10
- data/features/support/db/fixtures/thetas.rb +0 -10
- data/features/support/db/migrations/create_delayed_betas.rb +0 -17
- data/features/support/db/migrations/create_thetas.rb +0 -5
- data/features/support/db/mysql.rb +0 -3
- data/features/support/db/postgresql.rb +0 -3
- data/features/support/models/alpha.rb +0 -10
- data/features/support/models/delayed_beta.rb +0 -7
- data/features/support/models/theta.rb +0 -7
- data/features/support/post_database.rb +0 -43
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +0 -50
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +0 -24
- data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +0 -27
- data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -26
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +0 -30
- data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +0 -96
- data/spec/lib/thinking_sphinx/active_record_spec.rb +0 -353
- data/spec/lib/thinking_sphinx/deltas/job_spec.rb +0 -32
- data/spec/lib/thinking_sphinx/index_spec.rb +0 -45
- data/spec/lib/thinking_sphinx_spec.rb +0 -162
- data/vendor/after_commit/LICENSE +0 -20
- data/vendor/after_commit/README +0 -16
- data/vendor/after_commit/Rakefile +0 -22
- data/vendor/after_commit/init.rb +0 -8
- data/vendor/after_commit/lib/after_commit/active_record.rb +0 -114
- data/vendor/after_commit/lib/after_commit/connection_adapters.rb +0 -103
- data/vendor/after_commit/lib/after_commit.rb +0 -45
- data/vendor/after_commit/test/after_commit_test.rb +0 -53
- data/vendor/delayed_job/lib/delayed/job.rb +0 -251
- data/vendor/delayed_job/lib/delayed/message_sending.rb +0 -7
- data/vendor/delayed_job/lib/delayed/performable_method.rb +0 -55
- data/vendor/delayed_job/lib/delayed/worker.rb +0 -54
- data/vendor/riddle/lib/riddle/client/filter.rb +0 -53
- data/vendor/riddle/lib/riddle/client/message.rb +0 -66
- data/vendor/riddle/lib/riddle/client/response.rb +0 -84
- data/vendor/riddle/lib/riddle/client.rb +0 -635
- data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +0 -48
- data/vendor/riddle/lib/riddle/configuration/index.rb +0 -142
- data/vendor/riddle/lib/riddle/configuration/indexer.rb +0 -19
- data/vendor/riddle/lib/riddle/configuration/remote_index.rb +0 -17
- data/vendor/riddle/lib/riddle/configuration/searchd.rb +0 -25
- data/vendor/riddle/lib/riddle/configuration/section.rb +0 -43
- data/vendor/riddle/lib/riddle/configuration/source.rb +0 -23
- data/vendor/riddle/lib/riddle/configuration/sql_source.rb +0 -34
- data/vendor/riddle/lib/riddle/configuration/xml_source.rb +0 -28
- data/vendor/riddle/lib/riddle/configuration.rb +0 -33
- data/vendor/riddle/lib/riddle/controller.rb +0 -53
- data/vendor/riddle/lib/riddle.rb +0 -30
- data/features/{support → thinking_sphinx}/database.example.yml +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/alphas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/authors.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/boxes.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/categories.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/cats.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/dogs.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/extensible_betas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/gammas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/posts.rb +0 -0
- data/features/{support → thinking_sphinx}/db/fixtures/robots.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_animals.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_authors.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_authors_posts.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_betas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_boxes.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_categories.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_comments.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_extensible_betas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_gammas.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_people.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_posts.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_robots.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_taggings.rb +0 -0
- data/features/{support → thinking_sphinx}/db/migrations/create_tags.rb +0 -0
- data/features/{support → thinking_sphinx}/models/animal.rb +0 -0
- data/features/{support → thinking_sphinx}/models/author.rb +0 -0
- data/features/{support → thinking_sphinx}/models/box.rb +0 -0
- data/features/{support → thinking_sphinx}/models/cat.rb +0 -0
- data/features/{support → thinking_sphinx}/models/category.rb +0 -0
- data/features/{support → thinking_sphinx}/models/comment.rb +3 -3
- /data/features/{support → thinking_sphinx}/models/dog.rb +0 -0
- /data/features/{support → thinking_sphinx}/models/gamma.rb +0 -0
- /data/features/{support → thinking_sphinx}/models/robot.rb +0 -0
- /data/features/{support → thinking_sphinx}/models/tag.rb +0 -0
- /data/features/{support → thinking_sphinx}/models/tagging.rb +0 -0
|
@@ -93,25 +93,25 @@ module ThinkingSphinx
|
|
|
93
93
|
|
|
94
94
|
separator = all_ints? || all_datetimes? || @crc ? ',' : ' '
|
|
95
95
|
|
|
96
|
-
clause =
|
|
97
|
-
part = column_with_prefix(column)
|
|
96
|
+
clause = columns_with_prefixes.collect { |column|
|
|
98
97
|
case type
|
|
99
98
|
when :string
|
|
100
|
-
adapter.convert_nulls(
|
|
99
|
+
adapter.convert_nulls(column)
|
|
101
100
|
when :datetime
|
|
102
|
-
adapter.cast_to_datetime(
|
|
101
|
+
adapter.cast_to_datetime(column)
|
|
103
102
|
when :multi
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
column = adapter.cast_to_datetime(column) if is_many_datetimes?
|
|
104
|
+
column = adapter.convert_nulls(column, '0') if is_many_ints?
|
|
105
|
+
column
|
|
107
106
|
else
|
|
108
|
-
|
|
107
|
+
column
|
|
109
108
|
end
|
|
110
109
|
}.join(', ')
|
|
111
110
|
|
|
112
111
|
clause = adapter.crc(clause) if @crc
|
|
113
112
|
clause = adapter.concatenate(clause, separator) if concat_ws?
|
|
114
113
|
clause = adapter.group_concatenate(clause, separator) if is_many?
|
|
114
|
+
clause = adapter.downcase(clause) if insensitive?
|
|
115
115
|
|
|
116
116
|
"#{clause} AS #{quote_column(unique_name)}"
|
|
117
117
|
end
|
|
@@ -123,7 +123,8 @@ module ThinkingSphinx
|
|
|
123
123
|
:string => :sql_attr_str2ordinal,
|
|
124
124
|
:float => :sql_attr_float,
|
|
125
125
|
:boolean => :sql_attr_bool,
|
|
126
|
-
:integer => :sql_attr_uint
|
|
126
|
+
:integer => :sql_attr_uint,
|
|
127
|
+
:bigint => :sql_attr_bigint
|
|
127
128
|
}[type]
|
|
128
129
|
end
|
|
129
130
|
|
|
@@ -179,8 +180,12 @@ module ThinkingSphinx
|
|
|
179
180
|
def live_value(instance)
|
|
180
181
|
object = instance
|
|
181
182
|
column = @columns.first
|
|
182
|
-
column.__stack.each { |method|
|
|
183
|
-
|
|
183
|
+
column.__stack.each { |method|
|
|
184
|
+
object = object.send(method)
|
|
185
|
+
return sphinx_value(nil) if object.nil?
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
sphinx_value object.send(column.__name)
|
|
184
189
|
end
|
|
185
190
|
|
|
186
191
|
def all_ints?
|
|
@@ -297,19 +302,11 @@ WHERE #{@source.index.delta_object.clause(model, true)})
|
|
|
297
302
|
is_many? && all_strings?
|
|
298
303
|
end
|
|
299
304
|
|
|
300
|
-
def type_from_database
|
|
301
|
-
klass = @associations.values.flatten.first ?
|
|
302
|
-
@associations.values.flatten.first.reflection.klass : @model
|
|
303
|
-
|
|
304
|
-
column = klass.columns.detect { |col|
|
|
305
|
-
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
306
|
-
}
|
|
307
|
-
column.nil? ? nil : column.type
|
|
308
|
-
end
|
|
309
|
-
|
|
310
305
|
def translated_type_from_database
|
|
311
306
|
case type_from_db = type_from_database
|
|
312
|
-
when :
|
|
307
|
+
when :integer
|
|
308
|
+
integer_type_from_db
|
|
309
|
+
when :datetime, :string, :float, :boolean
|
|
313
310
|
type_from_db
|
|
314
311
|
when :decimal
|
|
315
312
|
:float
|
|
@@ -327,6 +324,32 @@ block:
|
|
|
327
324
|
end
|
|
328
325
|
end
|
|
329
326
|
|
|
327
|
+
def type_from_database
|
|
328
|
+
column = column_from_db
|
|
329
|
+
column.nil? ? nil : column.type
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def integer_type_from_db
|
|
333
|
+
column = column_from_db
|
|
334
|
+
return nil if column.nil?
|
|
335
|
+
|
|
336
|
+
case column.sql_type
|
|
337
|
+
when adapter.bigint_pattern
|
|
338
|
+
:bigint
|
|
339
|
+
else
|
|
340
|
+
:integer
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def column_from_db
|
|
345
|
+
klass = @associations.values.flatten.first ?
|
|
346
|
+
@associations.values.flatten.first.reflection.klass : @model
|
|
347
|
+
|
|
348
|
+
klass.columns.detect { |col|
|
|
349
|
+
@columns.collect { |c| c.__name.to_s }.include? col.name
|
|
350
|
+
}
|
|
351
|
+
end
|
|
352
|
+
|
|
330
353
|
def all_of_type?(*column_types)
|
|
331
354
|
@columns.all? { |col|
|
|
332
355
|
klasses = @associations[col].empty? ? [@model] :
|
|
@@ -337,5 +360,26 @@ block:
|
|
|
337
360
|
}
|
|
338
361
|
}
|
|
339
362
|
end
|
|
363
|
+
|
|
364
|
+
def sphinx_value(value)
|
|
365
|
+
case value
|
|
366
|
+
when TrueClass
|
|
367
|
+
1
|
|
368
|
+
when FalseClass, NilClass
|
|
369
|
+
0
|
|
370
|
+
when Time
|
|
371
|
+
value.to_i
|
|
372
|
+
when Date
|
|
373
|
+
value.to_time.to_i
|
|
374
|
+
when String
|
|
375
|
+
value.to_crc32
|
|
376
|
+
else
|
|
377
|
+
value
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def insensitive?
|
|
382
|
+
@sortable == :insensitive
|
|
383
|
+
end
|
|
340
384
|
end
|
|
341
|
-
end
|
|
385
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module ThinkingSphinx
|
|
2
|
+
class AutoVersion
|
|
3
|
+
def self.detect
|
|
4
|
+
version = ThinkingSphinx::Configuration.instance.version
|
|
5
|
+
case version
|
|
6
|
+
when '0.9.8', '0.9.9'
|
|
7
|
+
require "riddle/#{version}"
|
|
8
|
+
when '1.10-beta'
|
|
9
|
+
require 'riddle/1.10'
|
|
10
|
+
else
|
|
11
|
+
STDERR.puts %Q{
|
|
12
|
+
Sphinx cannot be found on your system. You may need to configure the following
|
|
13
|
+
settings in your config/sphinx.yml file:
|
|
14
|
+
* bin_path
|
|
15
|
+
* searchd_binary_name
|
|
16
|
+
* indexer_binary_name
|
|
17
|
+
|
|
18
|
+
For more information, read the documentation:
|
|
19
|
+
http://freelancing-god.github.com/ts/en/advanced_config.html
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module ThinkingSphinx
|
|
2
|
+
class BundledSearch
|
|
3
|
+
attr_reader :client
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@searches = []
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def search(*args)
|
|
10
|
+
@searches << ThinkingSphinx.search(*args)
|
|
11
|
+
@searches.last.append_to client
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def search_for_ids(*args)
|
|
15
|
+
@searches << ThinkingSphinx.search_for_ids(*args)
|
|
16
|
+
@searches.last.append_to client
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def searches
|
|
20
|
+
populate
|
|
21
|
+
@searches
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def client
|
|
27
|
+
@client ||= ThinkingSphinx::Configuration.instance.client
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def populated?
|
|
31
|
+
@populated
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def populate
|
|
35
|
+
return if populated?
|
|
36
|
+
|
|
37
|
+
@populated = true
|
|
38
|
+
|
|
39
|
+
client.run.each_with_index do |results, index|
|
|
40
|
+
searches[index].populate_from_queue results
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -8,8 +8,9 @@ module ThinkingSphinx
|
|
|
8
8
|
"class_crc"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def value(object,
|
|
12
|
-
|
|
11
|
+
def value(object, attribute_hash)
|
|
12
|
+
crc = attribute_hash['class_crc']
|
|
13
|
+
ThinkingSphinx::Configuration.instance.models_by_crc[crc]
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
@@ -13,7 +13,7 @@ module ThinkingSphinx
|
|
|
13
13
|
# pid file:: log/searchd.#{environment}.pid
|
|
14
14
|
# searchd files:: db/sphinx/#{environment}/
|
|
15
15
|
# address:: 127.0.0.1
|
|
16
|
-
# port::
|
|
16
|
+
# port:: 9312
|
|
17
17
|
# allow star:: false
|
|
18
18
|
# min prefix length:: 1
|
|
19
19
|
# min infix length:: 1
|
|
@@ -49,25 +49,29 @@ module ThinkingSphinx
|
|
|
49
49
|
class Configuration
|
|
50
50
|
include Singleton
|
|
51
51
|
|
|
52
|
-
SourceOptions = %w( mysql_connect_flags
|
|
53
|
-
|
|
52
|
+
SourceOptions = %w( mysql_connect_flags mysql_ssl_cert mysql_ssl_key
|
|
53
|
+
mysql_ssl_ca sql_range_step sql_query_pre sql_query_post
|
|
54
|
+
sql_query_killlist sql_ranged_throttle sql_query_post_index unpack_zlib
|
|
55
|
+
unpack_mysqlcompress unpack_mysqlcompress_maxsize )
|
|
54
56
|
|
|
55
|
-
IndexOptions = %w( charset_table charset_type
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
IndexOptions = %w( blend_chars charset_table charset_type charset_dictpath
|
|
58
|
+
docinfo enable_star exceptions expand_keywords hitless_words
|
|
59
|
+
html_index_attrs html_remove_elements html_strip index_exact_words
|
|
60
|
+
ignore_chars inplace_docinfo_gap inplace_enable inplace_hit_gap
|
|
61
|
+
inplace_reloc_factor inplace_write_factor min_infix_len min_prefix_len
|
|
62
|
+
min_stemming_len min_word_len mlock morphology ngram_chars ngram_len
|
|
63
|
+
ondisk_dict overshort_step phrase_boundary phrase_boundary_step preopen
|
|
64
|
+
stopwords stopwords_step wordforms )
|
|
60
65
|
|
|
61
66
|
CustomOptions = %w( disable_range )
|
|
62
67
|
|
|
63
|
-
attr_accessor :
|
|
64
|
-
:
|
|
65
|
-
:database_yml_file, :app_root, :bin_path, :model_directories,
|
|
66
|
-
:delayed_job_priority, :searchd_binary_name, :indexer_binary_name
|
|
68
|
+
attr_accessor :searchd_file_path, :allow_star, :database_yml_file,
|
|
69
|
+
:app_root, :model_directories, :delayed_job_priority, :indexed_models
|
|
67
70
|
|
|
68
71
|
attr_accessor :source_options, :index_options
|
|
72
|
+
attr_accessor :version
|
|
69
73
|
|
|
70
|
-
attr_reader :environment, :configuration
|
|
74
|
+
attr_reader :environment, :configuration, :controller
|
|
71
75
|
|
|
72
76
|
# Load in the configuration settings - this will look for config/sphinx.yml
|
|
73
77
|
# and parse it according to the current environment.
|
|
@@ -91,60 +95,64 @@ module ThinkingSphinx
|
|
|
91
95
|
end
|
|
92
96
|
|
|
93
97
|
@configuration = Riddle::Configuration.new
|
|
94
|
-
@configuration.searchd.address = "127.0.0.1"
|
|
95
|
-
@configuration.searchd.port = 3312
|
|
96
98
|
@configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
|
|
97
99
|
@configuration.searchd.log = "#{self.app_root}/log/searchd.log"
|
|
98
100
|
@configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
|
|
99
101
|
|
|
102
|
+
@controller = Riddle::Controller.new @configuration,
|
|
103
|
+
"#{self.app_root}/config/#{environment}.sphinx.conf"
|
|
104
|
+
|
|
105
|
+
self.address = "127.0.0.1"
|
|
106
|
+
self.port = 9312
|
|
100
107
|
self.database_yml_file = "#{self.app_root}/config/database.yml"
|
|
101
|
-
self.config_file = "#{self.app_root}/config/#{environment}.sphinx.conf"
|
|
102
108
|
self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
|
|
103
109
|
self.allow_star = false
|
|
104
|
-
self.bin_path = ""
|
|
105
110
|
self.model_directories = ["#{app_root}/app/models/"] +
|
|
106
111
|
Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
|
|
107
112
|
self.delayed_job_priority = 0
|
|
113
|
+
self.indexed_models = []
|
|
108
114
|
|
|
109
115
|
self.source_options = {}
|
|
110
116
|
self.index_options = {
|
|
111
117
|
:charset_type => "utf-8"
|
|
112
118
|
}
|
|
113
119
|
|
|
114
|
-
self.
|
|
115
|
-
self.indexer_binary_name = "indexer"
|
|
116
|
-
|
|
120
|
+
self.version = nil
|
|
117
121
|
parse_config
|
|
122
|
+
self.version ||= @controller.sphinx_version
|
|
118
123
|
|
|
119
124
|
self
|
|
120
125
|
end
|
|
121
126
|
|
|
122
127
|
def self.environment
|
|
123
|
-
|
|
124
|
-
defined?(Merb)
|
|
125
|
-
|
|
128
|
+
Thread.current[:thinking_sphinx_environment] ||= begin
|
|
129
|
+
if defined?(Merb)
|
|
130
|
+
Merb.environment
|
|
131
|
+
elsif defined?(RAILS_ENV)
|
|
132
|
+
RAILS_ENV
|
|
133
|
+
else
|
|
134
|
+
ENV['RAILS_ENV'] || 'development'
|
|
135
|
+
end
|
|
136
|
+
end
|
|
126
137
|
end
|
|
127
138
|
|
|
128
139
|
def environment
|
|
129
140
|
self.class.environment
|
|
130
141
|
end
|
|
131
142
|
|
|
132
|
-
def controller
|
|
133
|
-
@controller ||= Riddle::Controller.new(@configuration, self.config_file)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
143
|
# Generate the config file for Sphinx by using all the settings defined and
|
|
137
144
|
# looping through all the models with indexes to build the relevant
|
|
138
145
|
# indexer and searchd configuration, and sources and indexes details.
|
|
139
146
|
#
|
|
140
147
|
def build(file_path=nil)
|
|
141
|
-
load_models
|
|
142
148
|
file_path ||= "#{self.config_file}"
|
|
143
149
|
|
|
144
150
|
@configuration.indexes.clear
|
|
145
151
|
|
|
146
|
-
ThinkingSphinx.indexed_models.
|
|
147
|
-
|
|
152
|
+
ThinkingSphinx.context.indexed_models.each do |model|
|
|
153
|
+
model = model.constantize
|
|
154
|
+
model.define_indexes
|
|
155
|
+
@configuration.indexes.concat model.to_riddle
|
|
148
156
|
end
|
|
149
157
|
|
|
150
158
|
open(file_path, "w") do |file|
|
|
@@ -152,50 +160,21 @@ module ThinkingSphinx
|
|
|
152
160
|
end
|
|
153
161
|
end
|
|
154
162
|
|
|
155
|
-
# Make sure all models are loaded - without reloading any that
|
|
156
|
-
# ActiveRecord::Base is already aware of (otherwise we start to hit some
|
|
157
|
-
# messy dependencies issues).
|
|
158
|
-
#
|
|
159
|
-
def load_models
|
|
160
|
-
return if defined?(Rails) &&
|
|
161
|
-
Rails::VERSION::STRING.to_f > 2.1 &&
|
|
162
|
-
Rails.configuration.cache_classes
|
|
163
|
-
|
|
164
|
-
self.model_directories.each do |base|
|
|
165
|
-
Dir["#{base}**/*.rb"].each do |file|
|
|
166
|
-
model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
|
|
167
|
-
|
|
168
|
-
next if model_name.nil?
|
|
169
|
-
next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
|
|
170
|
-
model.name == model_name
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
begin
|
|
174
|
-
model_name.camelize.constantize
|
|
175
|
-
rescue LoadError
|
|
176
|
-
model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
|
|
177
|
-
rescue NameError
|
|
178
|
-
next
|
|
179
|
-
rescue StandardError
|
|
180
|
-
puts "Warning: Error loading #{file}"
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
163
|
def address
|
|
187
|
-
@
|
|
164
|
+
@address
|
|
188
165
|
end
|
|
189
166
|
|
|
190
167
|
def address=(address)
|
|
168
|
+
@address = address
|
|
191
169
|
@configuration.searchd.address = address
|
|
192
170
|
end
|
|
193
171
|
|
|
194
172
|
def port
|
|
195
|
-
@
|
|
173
|
+
@port
|
|
196
174
|
end
|
|
197
175
|
|
|
198
176
|
def port=(port)
|
|
177
|
+
@port = port
|
|
199
178
|
@configuration.searchd.port = port
|
|
200
179
|
end
|
|
201
180
|
|
|
@@ -223,15 +202,50 @@ module ThinkingSphinx
|
|
|
223
202
|
@configuration.searchd.query_log = file
|
|
224
203
|
end
|
|
225
204
|
|
|
205
|
+
def config_file
|
|
206
|
+
@controller.path
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def config_file=(file)
|
|
210
|
+
@controller.path = file
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def bin_path
|
|
214
|
+
@controller.bin_path
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def bin_path=(path)
|
|
218
|
+
@controller.bin_path = path
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def searchd_binary_name
|
|
222
|
+
@controller.searchd_binary_name
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def searchd_binary_name=(name)
|
|
226
|
+
@controller.searchd_binary_name = name
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def indexer_binary_name
|
|
230
|
+
@controller.indexer_binary_name
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def indexer_binary_name=(name)
|
|
234
|
+
@controller.indexer_binary_name = name
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
attr_accessor :timeout
|
|
238
|
+
|
|
226
239
|
def client
|
|
227
240
|
client = Riddle::Client.new address, port
|
|
228
241
|
client.max_matches = configuration.searchd.max_matches || 1000
|
|
242
|
+
client.timeout = timeout || 0
|
|
229
243
|
client
|
|
230
244
|
end
|
|
231
245
|
|
|
232
246
|
def models_by_crc
|
|
233
247
|
@models_by_crc ||= begin
|
|
234
|
-
ThinkingSphinx.indexed_models.inject({}) do |hash, model|
|
|
248
|
+
ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
|
|
235
249
|
hash[model.constantize.to_crc32] = model
|
|
236
250
|
Object.subclasses_of(model.constantize).each { |subclass|
|
|
237
251
|
hash[subclass.to_crc32] = subclass.name
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
class ThinkingSphinx::Context
|
|
2
|
+
attr_reader :indexed_models
|
|
3
|
+
|
|
4
|
+
def initialize(*models)
|
|
5
|
+
@indexed_models = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def prepare
|
|
9
|
+
ThinkingSphinx::Configuration.instance.indexed_models.each do |model|
|
|
10
|
+
add_indexed_model model
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
return unless indexed_models.empty?
|
|
14
|
+
|
|
15
|
+
load_models
|
|
16
|
+
add_indexed_models
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def define_indexes
|
|
20
|
+
indexed_models.each { |model|
|
|
21
|
+
model.constantize.define_indexes
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_indexed_model(model)
|
|
26
|
+
model = model.name if model.is_a?(Class)
|
|
27
|
+
|
|
28
|
+
indexed_models << model
|
|
29
|
+
indexed_models.uniq!
|
|
30
|
+
indexed_models.sort!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def superclass_indexed_models
|
|
34
|
+
klasses = indexed_models.collect { |name| name.constantize }
|
|
35
|
+
klasses.reject { |klass|
|
|
36
|
+
klass.superclass.ancestors.any? { |ancestor| klasses.include?(ancestor) }
|
|
37
|
+
}.collect { |klass| klass.name }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def add_indexed_models
|
|
43
|
+
Object.subclasses_of(ActiveRecord::Base).each do |klass|
|
|
44
|
+
add_indexed_model klass if klass.has_sphinx_indexes?
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Make sure all models are loaded - without reloading any that
|
|
49
|
+
# ActiveRecord::Base is already aware of (otherwise we start to hit some
|
|
50
|
+
# messy dependencies issues).
|
|
51
|
+
#
|
|
52
|
+
def load_models
|
|
53
|
+
ThinkingSphinx::Configuration.instance.model_directories.each do |base|
|
|
54
|
+
Dir["#{base}**/*.rb"].each do |file|
|
|
55
|
+
model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
|
|
56
|
+
|
|
57
|
+
next if model_name.nil?
|
|
58
|
+
next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
|
|
59
|
+
model.name == model_name.camelize
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
begin
|
|
63
|
+
model_name.camelize.constantize
|
|
64
|
+
rescue LoadError
|
|
65
|
+
model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
|
|
66
|
+
rescue NameError
|
|
67
|
+
next
|
|
68
|
+
rescue StandardError => err
|
|
69
|
+
STDERR.puts "Warning: Error loading #{file}:"
|
|
70
|
+
STDERR.puts err.message
|
|
71
|
+
STDERR.puts err.backtrace.join("\n"), ''
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -13,18 +13,8 @@ module ThinkingSphinx
|
|
|
13
13
|
ThinkingSphinx.deltas_enabled?
|
|
14
14
|
return true if instance && !toggled(instance)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
|
19
|
-
|
|
20
|
-
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} #{delta_index_name model}`
|
|
21
|
-
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
|
22
|
-
|
|
23
|
-
client.update(
|
|
24
|
-
core_index_name(model),
|
|
25
|
-
['sphinx_deleted'],
|
|
26
|
-
{instance.sphinx_document_id => [1]}
|
|
27
|
-
) if instance && ThinkingSphinx.sphinx_running? && instance.in_both_indexes?
|
|
16
|
+
update_delta_indexes model
|
|
17
|
+
delete_from_core model, instance if instance
|
|
28
18
|
|
|
29
19
|
true
|
|
30
20
|
end
|
|
@@ -48,17 +38,21 @@ module ThinkingSphinx
|
|
|
48
38
|
" = #{adapter.boolean(toggled)}"
|
|
49
39
|
end
|
|
50
40
|
|
|
51
|
-
|
|
41
|
+
private
|
|
52
42
|
|
|
53
|
-
def
|
|
54
|
-
|
|
43
|
+
def update_delta_indexes(model)
|
|
44
|
+
config = ThinkingSphinx::Configuration.instance
|
|
45
|
+
rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
|
|
46
|
+
|
|
47
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config "#{config.config_file}" #{rotate} #{model.delta_index_names.join(' ')}`
|
|
48
|
+
puts(output) unless ThinkingSphinx.suppress_delta_output?
|
|
55
49
|
end
|
|
56
50
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
def delete_from_core(model, instance)
|
|
52
|
+
model.core_index_names.each do |index_name|
|
|
53
|
+
model.delete_in_index index_name, instance.sphinx_document_id
|
|
54
|
+
end
|
|
55
|
+
end
|
|
62
56
|
|
|
63
57
|
def adapter
|
|
64
58
|
@adapter = @index.model.sphinx_database_adapter
|
|
@@ -93,7 +93,7 @@ DESC
|
|
|
93
93
|
rails_env = fetch(:rails_env, "production")
|
|
94
94
|
rake = fetch(:rake, "rake")
|
|
95
95
|
tasks.each do |t|
|
|
96
|
-
run "cd #{current_path}; #{rake} RAILS_ENV=#{rails_env} #{t}"
|
|
96
|
+
run "if [ -d #{release_path} ]; then cd #{release_path}; else cd #{current_path}; fi; #{rake} RAILS_ENV=#{rails_env} #{t}"
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
end
|
|
@@ -14,7 +14,7 @@ module ThinkingSphinx
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def method_missing(method, *args, &block)
|
|
17
|
-
string =
|
|
17
|
+
string = @instance.send(method, *args, &block).to_s
|
|
18
18
|
|
|
19
19
|
@search.excerpt_for(string, @instance.class)
|
|
20
20
|
end
|
|
@@ -71,7 +71,12 @@ module ThinkingSphinx
|
|
|
71
71
|
@property.is_a?(Field) ? :string : @property.type
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def
|
|
74
|
+
def float?
|
|
75
|
+
@property.type == :float
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def value(object, attribute_hash)
|
|
79
|
+
attribute_value = attribute_hash['@groupby']
|
|
75
80
|
return translate(object, attribute_value) if translate? || float?
|
|
76
81
|
|
|
77
82
|
case @property.type
|
|
@@ -117,9 +122,5 @@ module ThinkingSphinx
|
|
|
117
122
|
def column
|
|
118
123
|
@property.columns.first
|
|
119
124
|
end
|
|
120
|
-
|
|
121
|
-
def float?
|
|
122
|
-
@property.type == :float
|
|
123
|
-
end
|
|
124
125
|
end
|
|
125
126
|
end
|