thinking-sphinx 1.5.0 → 2.0.0.rc1
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 +15 -48
- data/VERSION +1 -0
- data/features/attribute_transformation.feature +7 -7
- data/features/attribute_updates.feature +16 -18
- data/features/deleting_instances.feature +13 -16
- data/features/excerpts.feature +0 -8
- data/features/facets.feature +19 -25
- data/features/handling_edits.feature +20 -25
- data/features/searching_across_models.feature +1 -1
- data/features/searching_by_index.feature +5 -6
- data/features/searching_by_model.feature +29 -29
- data/features/sphinx_scopes.feature +0 -26
- data/features/step_definitions/common_steps.rb +6 -18
- data/features/step_definitions/scope_steps.rb +0 -4
- data/features/step_definitions/search_steps.rb +4 -9
- data/features/support/env.rb +10 -3
- data/features/thinking_sphinx/db/fixtures/alphas.rb +10 -8
- data/features/thinking_sphinx/db/fixtures/cats.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/dogs.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/foxes.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/people.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/posts.rb +1 -5
- data/features/thinking_sphinx/db/migrations/create_posts.rb +0 -1
- data/features/thinking_sphinx/models/alpha.rb +0 -1
- data/features/thinking_sphinx/models/beta.rb +0 -5
- data/features/thinking_sphinx/models/developer.rb +1 -6
- data/features/thinking_sphinx/models/music.rb +1 -3
- data/features/thinking_sphinx/models/person.rb +1 -2
- data/features/thinking_sphinx/models/post.rb +0 -1
- data/lib/cucumber/thinking_sphinx/external_world.rb +4 -8
- data/lib/cucumber/thinking_sphinx/internal_world.rb +27 -36
- data/lib/thinking_sphinx.rb +60 -132
- data/lib/thinking_sphinx/active_record.rb +98 -124
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +13 -17
- data/lib/thinking_sphinx/active_record/delta.rb +15 -21
- data/lib/thinking_sphinx/active_record/has_many_association.rb +23 -16
- data/lib/thinking_sphinx/active_record/scopes.rb +0 -18
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +15 -63
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -4
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +24 -65
- data/lib/thinking_sphinx/association.rb +11 -36
- data/lib/thinking_sphinx/attribute.rb +85 -92
- data/lib/thinking_sphinx/auto_version.rb +3 -21
- data/lib/thinking_sphinx/class_facet.rb +3 -8
- data/lib/thinking_sphinx/configuration.rb +58 -114
- data/lib/thinking_sphinx/context.rb +20 -22
- data/lib/thinking_sphinx/core/array.rb +13 -0
- data/lib/thinking_sphinx/deltas.rb +0 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +22 -18
- data/lib/thinking_sphinx/deploy/capistrano.rb +31 -30
- data/lib/thinking_sphinx/excerpter.rb +1 -2
- data/lib/thinking_sphinx/facet.rb +35 -45
- data/lib/thinking_sphinx/facet_search.rb +24 -58
- data/lib/thinking_sphinx/field.rb +0 -18
- data/lib/thinking_sphinx/index.rb +36 -38
- data/lib/thinking_sphinx/index/builder.rb +59 -74
- data/lib/thinking_sphinx/property.rb +45 -66
- data/lib/thinking_sphinx/railtie.rb +35 -0
- data/lib/thinking_sphinx/search.rb +250 -506
- data/lib/thinking_sphinx/source.rb +31 -50
- data/lib/thinking_sphinx/source/internal_properties.rb +3 -8
- data/lib/thinking_sphinx/source/sql.rb +31 -71
- data/lib/thinking_sphinx/tasks.rb +27 -48
- data/spec/thinking_sphinx/active_record/delta_spec.rb +41 -36
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +0 -96
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +29 -29
- data/spec/thinking_sphinx/active_record_spec.rb +169 -140
- data/spec/thinking_sphinx/association_spec.rb +2 -20
- data/spec/thinking_sphinx/attribute_spec.rb +97 -101
- data/spec/thinking_sphinx/auto_version_spec.rb +11 -75
- data/spec/thinking_sphinx/configuration_spec.rb +62 -63
- data/spec/thinking_sphinx/context_spec.rb +66 -66
- data/spec/thinking_sphinx/facet_search_spec.rb +99 -99
- data/spec/thinking_sphinx/facet_spec.rb +4 -30
- data/spec/thinking_sphinx/field_spec.rb +3 -17
- data/spec/thinking_sphinx/index/builder_spec.rb +132 -169
- data/spec/thinking_sphinx/index_spec.rb +39 -45
- data/spec/thinking_sphinx/search_methods_spec.rb +33 -37
- data/spec/thinking_sphinx/search_spec.rb +269 -491
- data/spec/thinking_sphinx/source_spec.rb +48 -62
- data/spec/thinking_sphinx_spec.rb +49 -49
- data/tasks/distribution.rb +46 -0
- data/tasks/testing.rb +74 -0
- metadata +123 -199
- data/features/field_sorting.feature +0 -18
- data/features/thinking_sphinx/db/.gitignore +0 -1
- data/features/thinking_sphinx/db/fixtures/post_keywords.txt +0 -1
- data/features/thinking_sphinx/models/andrew.rb +0 -17
- data/lib/thinking-sphinx.rb +0 -1
- data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
- data/lib/thinking_sphinx/bundled_search.rb +0 -40
- data/lib/thinking_sphinx/connection.rb +0 -71
- data/lib/thinking_sphinx/deltas/delete_job.rb +0 -16
- data/lib/thinking_sphinx/deltas/index_job.rb +0 -17
- data/lib/thinking_sphinx/rails_additions.rb +0 -181
- data/spec/fixtures/data.sql +0 -32
- data/spec/fixtures/database.yml.default +0 -3
- data/spec/fixtures/models.rb +0 -161
- data/spec/fixtures/structure.sql +0 -146
- data/spec/spec_helper.rb +0 -54
- data/spec/sphinx_helper.rb +0 -67
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +0 -163
- data/spec/thinking_sphinx/connection_spec.rb +0 -77
- data/spec/thinking_sphinx/rails_additions_spec.rb +0 -203
|
@@ -19,8 +19,6 @@ module ThinkingSphinx
|
|
|
19
19
|
# - :sortable => true
|
|
20
20
|
# - :infixes => true
|
|
21
21
|
# - :prefixes => true
|
|
22
|
-
# - :file => true
|
|
23
|
-
# - :with => :attribute # or :wordcount
|
|
24
22
|
#
|
|
25
23
|
# Alias is only required in three circumstances: when there's
|
|
26
24
|
# another attribute or field with the same name, when the column name is
|
|
@@ -60,8 +58,6 @@ module ThinkingSphinx
|
|
|
60
58
|
@sortable = options[:sortable] || false
|
|
61
59
|
@infixes = options[:infixes] || false
|
|
62
60
|
@prefixes = options[:prefixes] || false
|
|
63
|
-
@file = options[:file] || false
|
|
64
|
-
@with = options[:with]
|
|
65
61
|
|
|
66
62
|
source.fields << self
|
|
67
63
|
end
|
|
@@ -73,8 +69,6 @@ module ThinkingSphinx
|
|
|
73
69
|
# multiple data values (has_many or has_and_belongs_to_many associations).
|
|
74
70
|
#
|
|
75
71
|
def to_select_sql
|
|
76
|
-
return nil unless available?
|
|
77
|
-
|
|
78
72
|
clause = columns_with_prefixes.join(', ')
|
|
79
73
|
|
|
80
74
|
clause = adapter.concatenate(clause) if concat_ws?
|
|
@@ -82,17 +76,5 @@ module ThinkingSphinx
|
|
|
82
76
|
|
|
83
77
|
"#{clause} AS #{quote_column(unique_name)}"
|
|
84
78
|
end
|
|
85
|
-
|
|
86
|
-
def file?
|
|
87
|
-
@file
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def with_attribute?
|
|
91
|
-
@with == :attribute
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def with_wordcount?
|
|
95
|
-
@with == :wordcount
|
|
96
|
-
end
|
|
97
79
|
end
|
|
98
80
|
end
|
|
@@ -3,8 +3,8 @@ require 'thinking_sphinx/index/faux_column'
|
|
|
3
3
|
|
|
4
4
|
module ThinkingSphinx
|
|
5
5
|
class Index
|
|
6
|
-
attr_accessor :name, :model, :sources, :delta_object
|
|
7
|
-
|
|
6
|
+
attr_accessor :name, :model, :sources, :delta_object
|
|
7
|
+
|
|
8
8
|
# Create a new index instance by passing in the model it is tied to, and
|
|
9
9
|
# a block to build it with (optional but recommended). For documentation
|
|
10
10
|
# on the syntax for inside the block, the Builder class is what you want.
|
|
@@ -13,9 +13,9 @@ module ThinkingSphinx
|
|
|
13
13
|
#
|
|
14
14
|
# Index.new(User) do
|
|
15
15
|
# indexes login, email
|
|
16
|
-
#
|
|
16
|
+
#
|
|
17
17
|
# has created_at
|
|
18
|
-
#
|
|
18
|
+
#
|
|
19
19
|
# set_property :delta => true
|
|
20
20
|
# end
|
|
21
21
|
#
|
|
@@ -25,48 +25,47 @@ module ThinkingSphinx
|
|
|
25
25
|
@sources = []
|
|
26
26
|
@options = {}
|
|
27
27
|
@delta_object = nil
|
|
28
|
-
@additional_indices = []
|
|
29
28
|
end
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
def fields
|
|
32
31
|
@sources.collect { |source| source.fields }.flatten
|
|
33
32
|
end
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
def attributes
|
|
36
35
|
@sources.collect { |source| source.attributes }.flatten
|
|
37
36
|
end
|
|
38
|
-
|
|
37
|
+
|
|
39
38
|
def core_name
|
|
40
39
|
"#{name}_core"
|
|
41
40
|
end
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
def delta_name
|
|
44
43
|
"#{name}_delta"
|
|
45
44
|
end
|
|
46
|
-
|
|
45
|
+
|
|
47
46
|
def all_names
|
|
48
47
|
names = [core_name]
|
|
49
48
|
names << delta_name if delta?
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
names
|
|
52
51
|
end
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
def self.name_for(model)
|
|
55
54
|
model.name.underscore.tr(':/\\', '_')
|
|
56
55
|
end
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
def prefix_fields
|
|
59
58
|
fields.select { |field| field.prefixes }
|
|
60
59
|
end
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
def infix_fields
|
|
63
62
|
fields.select { |field| field.infixes }
|
|
64
63
|
end
|
|
65
|
-
|
|
64
|
+
|
|
66
65
|
def local_options
|
|
67
66
|
@options
|
|
68
67
|
end
|
|
69
|
-
|
|
68
|
+
|
|
70
69
|
def options
|
|
71
70
|
all_index_options = config.index_options.clone
|
|
72
71
|
@options.keys.select { |key|
|
|
@@ -75,83 +74,82 @@ module ThinkingSphinx
|
|
|
75
74
|
}.each { |key| all_index_options[key.to_sym] = @options[key] }
|
|
76
75
|
all_index_options
|
|
77
76
|
end
|
|
78
|
-
|
|
77
|
+
|
|
79
78
|
def delta?
|
|
80
79
|
!@delta_object.nil?
|
|
81
80
|
end
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
def to_riddle(offset)
|
|
84
83
|
indexes = [to_riddle_for_core(offset)]
|
|
85
84
|
indexes << to_riddle_for_delta(offset) if delta?
|
|
86
85
|
indexes << to_riddle_for_distributed
|
|
87
86
|
end
|
|
88
|
-
|
|
87
|
+
|
|
89
88
|
private
|
|
90
|
-
|
|
89
|
+
|
|
91
90
|
def adapter
|
|
92
91
|
@adapter ||= @model.sphinx_database_adapter
|
|
93
92
|
end
|
|
94
|
-
|
|
93
|
+
|
|
95
94
|
def utf8?
|
|
96
95
|
options[:charset_type] == "utf-8"
|
|
97
96
|
end
|
|
98
|
-
|
|
97
|
+
|
|
99
98
|
def sql_query_pre_for_delta
|
|
100
99
|
[""]
|
|
101
100
|
end
|
|
102
|
-
|
|
101
|
+
|
|
103
102
|
def config
|
|
104
103
|
@config ||= ThinkingSphinx::Configuration.instance
|
|
105
104
|
end
|
|
106
|
-
|
|
105
|
+
|
|
107
106
|
def to_riddle_for_core(offset)
|
|
108
107
|
index = Riddle::Configuration::Index.new core_name
|
|
109
108
|
index.path = File.join config.searchd_file_path, index.name
|
|
110
|
-
|
|
109
|
+
|
|
111
110
|
set_configuration_options_for_indexes index
|
|
112
111
|
set_field_settings_for_indexes index
|
|
113
|
-
|
|
112
|
+
|
|
114
113
|
sources.each_with_index do |source, i|
|
|
115
114
|
index.sources << source.to_riddle_for_core(offset, i)
|
|
116
115
|
end
|
|
117
|
-
|
|
116
|
+
|
|
118
117
|
index
|
|
119
118
|
end
|
|
120
|
-
|
|
119
|
+
|
|
121
120
|
def to_riddle_for_delta(offset)
|
|
122
121
|
index = Riddle::Configuration::Index.new delta_name
|
|
123
122
|
index.parent = core_name
|
|
124
123
|
index.path = File.join config.searchd_file_path, index.name
|
|
125
|
-
|
|
124
|
+
|
|
126
125
|
sources.each_with_index do |source, i|
|
|
127
126
|
index.sources << source.to_riddle_for_delta(offset, i)
|
|
128
127
|
end
|
|
129
|
-
|
|
128
|
+
|
|
130
129
|
index
|
|
131
130
|
end
|
|
132
|
-
|
|
131
|
+
|
|
133
132
|
def to_riddle_for_distributed
|
|
134
133
|
index = Riddle::Configuration::DistributedIndex.new name
|
|
135
|
-
index.
|
|
136
|
-
index.
|
|
137
|
-
index.local_indices.unshift delta_name if delta?
|
|
134
|
+
index.local_indexes << core_name
|
|
135
|
+
index.local_indexes.unshift delta_name if delta?
|
|
138
136
|
index
|
|
139
137
|
end
|
|
140
|
-
|
|
138
|
+
|
|
141
139
|
def set_configuration_options_for_indexes(index)
|
|
142
140
|
config.index_options.each do |key, value|
|
|
143
141
|
method = "#{key}=".to_sym
|
|
144
142
|
index.send(method, value) if index.respond_to?(method)
|
|
145
143
|
end
|
|
146
|
-
|
|
144
|
+
|
|
147
145
|
options.each do |key, value|
|
|
148
146
|
index.send("#{key}=".to_sym, value) if ThinkingSphinx::Configuration::IndexOptions.include?(key.to_s) && !value.nil?
|
|
149
147
|
end
|
|
150
148
|
end
|
|
151
|
-
|
|
149
|
+
|
|
152
150
|
def set_field_settings_for_indexes(index)
|
|
153
151
|
field_names = lambda { |field| field.unique_name.to_s }
|
|
154
|
-
|
|
152
|
+
|
|
155
153
|
index.prefix_field_names += prefix_fields.collect(&field_names)
|
|
156
154
|
index.infix_field_names += infix_fields.collect(&field_names)
|
|
157
155
|
end
|
|
@@ -11,7 +11,7 @@ module ThinkingSphinx
|
|
|
11
11
|
# your indexes. #where provides a method to add manual SQL conditions, and
|
|
12
12
|
# set_property allows you to set some settings on a per-index basis. Check
|
|
13
13
|
# out each method's documentation for better ideas of usage.
|
|
14
|
-
#
|
|
14
|
+
#
|
|
15
15
|
class Builder
|
|
16
16
|
instance_methods.grep(/^[^_]/).each { |method|
|
|
17
17
|
next if method.to_s == "instance_eval"
|
|
@@ -19,28 +19,28 @@ module ThinkingSphinx
|
|
|
19
19
|
caller.grep(/irb.completion/).empty? ? method_missing(method) : super
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
def self.generate(model, name = nil, &block)
|
|
24
24
|
index = ThinkingSphinx::Index.new(model)
|
|
25
25
|
index.name = name unless name.nil?
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
Builder.new(index, &block) if block_given?
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
index.delta_object = ThinkingSphinx::Deltas.parse index
|
|
30
30
|
index
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def initialize(index, &block)
|
|
34
34
|
@index = index
|
|
35
35
|
@explicit_source = false
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
self.instance_eval &block
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
if no_fields?
|
|
40
40
|
raise "At least one field is necessary for an index"
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
def define_source(&block)
|
|
45
45
|
if @explicit_source
|
|
46
46
|
@source = ThinkingSphinx::Source.new(@index)
|
|
@@ -48,15 +48,10 @@ module ThinkingSphinx
|
|
|
48
48
|
else
|
|
49
49
|
@explicit_source = true
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
self.instance_eval &block
|
|
53
53
|
end
|
|
54
|
-
|
|
55
|
-
def use_local_indices(*indexes)
|
|
56
|
-
@index.additional_indices += indexes.map {|index_name| "#{index_name.to_s}_core"}
|
|
57
|
-
end
|
|
58
|
-
alias_method :use_local_index, :use_local_indices
|
|
59
|
-
|
|
54
|
+
|
|
60
55
|
# This is how you add fields - the strings Sphinx looks at - to your
|
|
61
56
|
# index. Technically, to use this method, you need to pass in some
|
|
62
57
|
# columns and options - but there's some neat method_missing stuff
|
|
@@ -68,26 +63,26 @@ module ThinkingSphinx
|
|
|
68
63
|
# field.
|
|
69
64
|
#
|
|
70
65
|
# Adding Single-Column Fields:
|
|
71
|
-
#
|
|
66
|
+
#
|
|
72
67
|
# You can use symbols or methods - and can chain methods together to
|
|
73
68
|
# get access down the associations tree.
|
|
74
|
-
#
|
|
69
|
+
#
|
|
75
70
|
# indexes :id, :as => :my_id
|
|
76
71
|
# indexes :name, :sortable => true
|
|
77
72
|
# indexes first_name, last_name, :sortable => true
|
|
78
73
|
# indexes users.posts.content, :as => :post_content
|
|
79
74
|
# indexes users(:id), :as => :user_ids
|
|
80
75
|
#
|
|
81
|
-
# Keep in mind that if any keywords for Ruby methods - such as id or
|
|
76
|
+
# Keep in mind that if any keywords for Ruby methods - such as id or
|
|
82
77
|
# name - clash with your column names, you need to use the symbol
|
|
83
78
|
# version (see the first, second and last examples above).
|
|
84
79
|
#
|
|
85
80
|
# If you specify multiple columns (example #2), a field will be created
|
|
86
81
|
# for each. Don't use the :as option in this case. If you want to merge
|
|
87
82
|
# those columns together, continue reading.
|
|
88
|
-
#
|
|
83
|
+
#
|
|
89
84
|
# Adding Multi-Column Fields:
|
|
90
|
-
#
|
|
85
|
+
#
|
|
91
86
|
# indexes [first_name, last_name], :as => :name
|
|
92
87
|
# indexes [location, parent.location], :as => :location
|
|
93
88
|
#
|
|
@@ -95,7 +90,7 @@ module ThinkingSphinx
|
|
|
95
90
|
# them in an Array, as shown by the above examples. There's no
|
|
96
91
|
# limitations on whether they're symbols or methods or what level of
|
|
97
92
|
# associations they come from.
|
|
98
|
-
#
|
|
93
|
+
#
|
|
99
94
|
# Adding SQL Fragment Fields
|
|
100
95
|
#
|
|
101
96
|
# You can also define a field using an SQL fragment, useful for when
|
|
@@ -107,37 +102,37 @@ module ThinkingSphinx
|
|
|
107
102
|
options = args.extract_options!
|
|
108
103
|
args.each do |columns|
|
|
109
104
|
field = Field.new(source, FauxColumn.coerce(columns), options)
|
|
110
|
-
|
|
105
|
+
|
|
111
106
|
add_sort_attribute field, options if field.sortable
|
|
112
107
|
add_facet_attribute field, options if field.faceted
|
|
113
108
|
end
|
|
114
109
|
end
|
|
115
|
-
|
|
110
|
+
|
|
116
111
|
# This is the method to add attributes to your index (hence why it is
|
|
117
112
|
# aliased as 'attribute'). The syntax is the same as #indexes, so use
|
|
118
113
|
# that as starting point, but keep in mind the following points.
|
|
119
|
-
#
|
|
114
|
+
#
|
|
120
115
|
# An attribute can have an alias (the :as option), but it is always
|
|
121
116
|
# sortable - so you don't need to explicitly request that. You _can_
|
|
122
117
|
# specify the data type of the attribute (the :type option), but the
|
|
123
118
|
# code's pretty good at figuring that out itself from peering into the
|
|
124
119
|
# database.
|
|
125
|
-
#
|
|
120
|
+
#
|
|
126
121
|
# Attributes are limited to the following types: integers, floats,
|
|
127
122
|
# datetimes (converted to timestamps), booleans, strings and MVAs
|
|
128
123
|
# (:multi). Don't forget that Sphinx converts string attributes to
|
|
129
124
|
# integers, which are useful for sorting, but that's about it.
|
|
130
|
-
#
|
|
125
|
+
#
|
|
131
126
|
# Collection of integers are known as multi-value attributes (MVAs).
|
|
132
127
|
# Generally these would be through a has_many relationship, like in this
|
|
133
128
|
# example:
|
|
134
|
-
#
|
|
129
|
+
#
|
|
135
130
|
# has posts(:id), :as => :post_ids
|
|
136
|
-
#
|
|
131
|
+
#
|
|
137
132
|
# This allows you to filter on any of the values tied to a specific
|
|
138
133
|
# record. Might be best to read through the Sphinx documentation to get
|
|
139
134
|
# a better idea of that though.
|
|
140
|
-
#
|
|
135
|
+
#
|
|
141
136
|
# Adding SQL Fragment Attributes
|
|
142
137
|
#
|
|
143
138
|
# You can also define an attribute using an SQL fragment, useful for
|
|
@@ -145,68 +140,68 @@ module ThinkingSphinx
|
|
|
145
140
|
# the type of the attribute though:
|
|
146
141
|
#
|
|
147
142
|
# has "age < 18", :as => :minor, :type => :boolean
|
|
148
|
-
#
|
|
143
|
+
#
|
|
149
144
|
# If you're creating attributes for latitude and longitude, don't
|
|
150
145
|
# forget that Sphinx expects these values to be in radians.
|
|
151
|
-
#
|
|
146
|
+
#
|
|
152
147
|
def has(*args)
|
|
153
148
|
options = args.extract_options!
|
|
154
149
|
args.each do |columns|
|
|
155
150
|
attribute = Attribute.new(source, FauxColumn.coerce(columns), options)
|
|
156
|
-
|
|
151
|
+
|
|
157
152
|
add_facet_attribute attribute, options if attribute.faceted
|
|
158
153
|
end
|
|
159
154
|
end
|
|
160
|
-
|
|
155
|
+
|
|
161
156
|
def facet(*args)
|
|
162
157
|
options = args.extract_options!
|
|
163
158
|
options[:facet] = true
|
|
164
|
-
|
|
159
|
+
|
|
165
160
|
args.each do |columns|
|
|
166
161
|
attribute = Attribute.new(source, FauxColumn.coerce(columns), options)
|
|
167
|
-
|
|
162
|
+
|
|
168
163
|
add_facet_attribute attribute, options
|
|
169
164
|
end
|
|
170
165
|
end
|
|
171
|
-
|
|
166
|
+
|
|
172
167
|
def join(*args)
|
|
173
168
|
args.each do |association|
|
|
174
169
|
Join.new(source, association)
|
|
175
170
|
end
|
|
176
171
|
end
|
|
177
|
-
|
|
172
|
+
|
|
178
173
|
# Use this method to add some manual SQL conditions for your index
|
|
179
174
|
# request. You can pass in as many strings as you like, they'll get
|
|
180
175
|
# joined together with ANDs later on.
|
|
181
|
-
#
|
|
176
|
+
#
|
|
182
177
|
# where "user_id = 10"
|
|
183
178
|
# where "parent_type = 'Article'", "created_at < NOW()"
|
|
184
|
-
#
|
|
179
|
+
#
|
|
185
180
|
def where(*args)
|
|
186
181
|
source.conditions += args
|
|
187
182
|
end
|
|
188
|
-
|
|
183
|
+
|
|
189
184
|
# Use this method to add some manual SQL strings to the GROUP BY
|
|
190
185
|
# clause. You can pass in as many strings as you'd like, they'll get
|
|
191
186
|
# joined together with commas later on.
|
|
192
|
-
#
|
|
187
|
+
#
|
|
193
188
|
# group_by "lat", "lng"
|
|
194
|
-
#
|
|
189
|
+
#
|
|
195
190
|
def group_by(*args)
|
|
196
191
|
source.groupings += args
|
|
197
192
|
end
|
|
198
|
-
|
|
193
|
+
|
|
199
194
|
# This is what to use to set properties on the index. Chief amongst
|
|
200
195
|
# those is the delta property - to allow automatic updates to your
|
|
201
196
|
# indexes as new models are added and edited - but also you can
|
|
202
197
|
# define search-related properties which will be the defaults for all
|
|
203
198
|
# searches on the model.
|
|
204
|
-
#
|
|
199
|
+
#
|
|
205
200
|
# set_property :delta => true
|
|
206
201
|
# set_property :field_weights => {"name" => 100}
|
|
207
202
|
# set_property :order => "name ASC"
|
|
208
203
|
# set_property :select => 'name'
|
|
209
|
-
#
|
|
204
|
+
#
|
|
210
205
|
# Also, the following two properties are particularly relevant for
|
|
211
206
|
# geo-location searching - latitude_attr and longitude_attr. If your
|
|
212
207
|
# attributes for these two values are named something other than
|
|
@@ -215,59 +210,49 @@ module ThinkingSphinx
|
|
|
215
210
|
# geo-related search.
|
|
216
211
|
#
|
|
217
212
|
# set_property :latitude_attr => "lt", :longitude_attr => "lg"
|
|
218
|
-
#
|
|
213
|
+
#
|
|
219
214
|
# Please don't forget to add a boolean field named 'delta' to your
|
|
220
215
|
# model's database table if enabling the delta index for it.
|
|
221
216
|
# Valid options for the delta property are:
|
|
222
|
-
#
|
|
217
|
+
#
|
|
223
218
|
# true
|
|
224
219
|
# false
|
|
225
220
|
# :default
|
|
226
221
|
# :delayed
|
|
227
222
|
# :datetime
|
|
228
|
-
#
|
|
229
|
-
# You can also extend ThinkingSphinx::Deltas::DefaultDelta to implement
|
|
223
|
+
#
|
|
224
|
+
# You can also extend ThinkingSphinx::Deltas::DefaultDelta to implement
|
|
230
225
|
# your own handling for delta indexing.
|
|
231
|
-
#
|
|
226
|
+
#
|
|
232
227
|
def set_property(*args)
|
|
233
228
|
options = args.extract_options!
|
|
234
229
|
options.each do |key, value|
|
|
235
230
|
set_single_property key, value
|
|
236
231
|
end
|
|
237
|
-
|
|
232
|
+
|
|
238
233
|
set_single_property args[0], args[1] if args.length == 2
|
|
239
234
|
end
|
|
240
235
|
alias_method :set_properties, :set_property
|
|
241
|
-
|
|
236
|
+
|
|
242
237
|
# Handles the generation of new columns for the field and attribute
|
|
243
238
|
# definitions.
|
|
244
|
-
#
|
|
239
|
+
#
|
|
245
240
|
def method_missing(method, *args)
|
|
246
241
|
FauxColumn.new(method, *args)
|
|
247
242
|
end
|
|
248
|
-
|
|
243
|
+
|
|
249
244
|
# A method to allow adding fields from associations which have names
|
|
250
245
|
# that clash with method names in the Builder class (ie: properties,
|
|
251
246
|
# fields, attributes).
|
|
252
|
-
#
|
|
247
|
+
#
|
|
253
248
|
# Example: indexes assoc(:properties).column
|
|
254
|
-
#
|
|
249
|
+
#
|
|
255
250
|
def assoc(assoc, *args)
|
|
256
251
|
FauxColumn.new(assoc, *args)
|
|
257
252
|
end
|
|
258
|
-
|
|
259
|
-
# Use this method to generate SQL for your attributes, conditions, etc.
|
|
260
|
-
# You can pass in as whatever ActiveRecord::Base.sanitize_sql accepts.
|
|
261
|
-
#
|
|
262
|
-
# where sanitize_sql(["active = ?", true])
|
|
263
|
-
# #=> WHERE active = 1
|
|
264
|
-
#
|
|
265
|
-
def sanitize_sql(*args)
|
|
266
|
-
@index.model.send(:sanitize_sql, *args)
|
|
267
|
-
end
|
|
268
|
-
|
|
253
|
+
|
|
269
254
|
private
|
|
270
|
-
|
|
255
|
+
|
|
271
256
|
def source
|
|
272
257
|
@source ||= begin
|
|
273
258
|
source = ThinkingSphinx::Source.new(@index)
|
|
@@ -275,7 +260,7 @@ module ThinkingSphinx
|
|
|
275
260
|
source
|
|
276
261
|
end
|
|
277
262
|
end
|
|
278
|
-
|
|
263
|
+
|
|
279
264
|
def set_single_property(key, value)
|
|
280
265
|
source_options = ThinkingSphinx::Configuration::SourceOptions
|
|
281
266
|
if source_options.include?(key.to_s)
|
|
@@ -284,19 +269,19 @@ module ThinkingSphinx
|
|
|
284
269
|
@index.local_options.merge! key => value
|
|
285
270
|
end
|
|
286
271
|
end
|
|
287
|
-
|
|
272
|
+
|
|
288
273
|
def add_sort_attribute(field, options)
|
|
289
274
|
add_internal_attribute field, options, "_sort"
|
|
290
275
|
end
|
|
291
|
-
|
|
276
|
+
|
|
292
277
|
def add_facet_attribute(property, options)
|
|
293
278
|
add_internal_attribute property, options, "_facet", true
|
|
294
279
|
@index.model.sphinx_facets << property.to_facet
|
|
295
280
|
end
|
|
296
|
-
|
|
281
|
+
|
|
297
282
|
def add_internal_attribute(property, options, suffix, crc = false)
|
|
298
283
|
return unless ThinkingSphinx::Facet.translate?(property)
|
|
299
|
-
|
|
284
|
+
|
|
300
285
|
Attribute.new(source,
|
|
301
286
|
property.columns.collect { |col| col.clone },
|
|
302
287
|
options.merge(
|
|
@@ -306,7 +291,7 @@ module ThinkingSphinx
|
|
|
306
291
|
).except(:facet)
|
|
307
292
|
)
|
|
308
293
|
end
|
|
309
|
-
|
|
294
|
+
|
|
310
295
|
def no_fields?
|
|
311
296
|
@index.sources.empty? || @index.sources.any? { |source|
|
|
312
297
|
source.fields.length == 0
|