ultrasphinx 1.7 → 1.8
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +2 -0
- data/README +12 -8
- data/examples/default.base +5 -2
- data/lib/ultrasphinx/associations.rb +8 -7
- data/lib/ultrasphinx/configure.rb +10 -10
- data/lib/ultrasphinx/core_extensions.rb +12 -1
- data/lib/ultrasphinx/fields.rb +23 -13
- data/lib/ultrasphinx/is_indexed.rb +2 -2
- data/lib/ultrasphinx/postgresql/crc32.sql +11 -3
- data/lib/ultrasphinx/search.rb +3 -2
- data/lib/ultrasphinx/search/internals.rb +18 -5
- data/lib/ultrasphinx/ultrasphinx.rb +2 -0
- data/tasks/ultrasphinx.rake +2 -2
- data/test/integration/app/app/models/person/user.rb +2 -2
- data/test/integration/app/config/boot.rb +2 -0
- data/test/integration/app/config/environment.rb +4 -3
- data/test/integration/app/config/ultrasphinx/default.base +33 -9
- data/test/integration/app/config/ultrasphinx/development.conf.canonical +58 -58
- data/test/integration/search_test.rb +4 -2
- data/test/integration/server_test.rb +1 -1
- data/test/test_helper.rb +10 -3
- data/ultrasphinx.gemspec +3 -3
- data/vendor/riddle/README +2 -2
- data/vendor/riddle/Rakefile +3 -6
- data/vendor/riddle/lib/riddle.rb +2 -1
- data/vendor/riddle/lib/riddle/client.rb +31 -8
- data/vendor/riddle/lib/riddle/client/message.rb +10 -1
- data/vendor/riddle/lib/riddle/client/response.rb +7 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
|
2
|
+
v1.8. Update client for compatibility with Sphinx 0.9.8 r1112. This is a breaking release! You need to update Sphinx along with Ultrasphinx. Float range bugfix; text faceting on association_include bugfix. Postgres users, please note that the return type of CRC32() has changed to bigint.
|
3
|
+
|
2
4
|
v1.7. Deployment docs. Postgres fixes. Support association_name instead of class_name (Daniel Higginbotham).
|
3
5
|
|
4
6
|
v1.6.7. Fix GROUP_CONCAT aggregate problem. Discourage enable_star in default.base. Allow faceting on includes.
|
data/README
CHANGED
@@ -5,17 +5,19 @@ Ruby on Rails configurator and client to the Sphinx full text search engine.
|
|
5
5
|
|
6
6
|
== License
|
7
7
|
|
8
|
-
Copyright
|
8
|
+
Copyright 2008 Cloudburst, LLC. Licensed under the AFL 3. See the included LICENSE file. Some portions copyright Pat Allan, distributed under the MIT license, and used with permission. Some portions copyright PJ Hyett and Mislav Marohnić, distributed under the MIT license, and used with permission.
|
9
9
|
|
10
|
-
The public certificate for the gem is
|
10
|
+
The public certificate for the gem is here[http://rubyforge.org/frs/download.php/25331/evan_weaver-original-public_cert.pem].
|
11
|
+
|
12
|
+
If you use this software, please {make a donation}[http://blog.evanweaver.com/donate/], or {recommend Evan}[http://www.workingwithrails.com/person/7739-evan-weaver] at Working with Rails.
|
11
13
|
|
12
14
|
== Requirements
|
13
15
|
|
14
16
|
* MySQL 5.0, or PostgreSQL 8.2
|
15
|
-
* Sphinx 0.9.8-dev
|
16
|
-
* Rails
|
17
|
+
* Sphinx 0.9.8-dev r1112
|
18
|
+
* Rails 2.0.2
|
17
19
|
|
18
|
-
More recent versions than listed are ok.
|
20
|
+
More recent versions than listed are usually ok.
|
19
21
|
|
20
22
|
== Features
|
21
23
|
|
@@ -45,7 +47,7 @@ And some other things.
|
|
45
47
|
|
46
48
|
== Installation
|
47
49
|
|
48
|
-
First, install Sphinx itself. Get the 0.9.8
|
50
|
+
First, install Sphinx itself. Get the {0.9.8 snapshot}[http://www.sphinxsearch.com/downloads.html], then run <tt>./configure</tt>, <tt>make</tt>, and <tt>sudo make install</tt>. Make sure to set your <tt>./configure</tt> flags: <tt>----prefix</tt> if necessary, and also <tt>----with-pgsql</tt> if you need Postgres support.
|
49
51
|
|
50
52
|
You also need the <tt>chronic</tt> gem:
|
51
53
|
sudo gem install chronic
|
@@ -53,7 +55,7 @@ You also need the <tt>chronic</tt> gem:
|
|
53
55
|
Then, install the plugin:
|
54
56
|
script/plugin install -x svn://rubyforge.org/var/svn/fauna/ultrasphinx/trunk
|
55
57
|
|
56
|
-
Next, copy the <tt>
|
58
|
+
Next, copy the <tt>examples/default.base</tt> file to <tt>RAILS_ROOT/config/ultrasphinx/default.base</tt>. This file sets up the Sphinx daemon options such as port, host, and index location.
|
57
59
|
|
58
60
|
If you need per-environment configuration, you can use <tt>RAILS_ROOT/config/ultrasphinx/development.base</tt>, etc.
|
59
61
|
|
@@ -109,10 +111,12 @@ PostgreSQL 8.2 and higher are well supported. However, make sure you have execut
|
|
109
111
|
|
110
112
|
== Reporting problems
|
111
113
|
|
112
|
-
|
114
|
+
The support forum is here[http://rubyforge.org/forum/forum.php?forum_id=14244].
|
113
115
|
|
114
116
|
Patches and contributions are very welcome. Please note that contributors are required to assign copyright for their additions to Cloudburst, LLC.
|
115
117
|
|
116
118
|
== Further resources
|
117
119
|
|
120
|
+
* http://sphinxsearch.com/doc.html
|
121
|
+
* http://sphinxsearch.com/forum/forum.html?id=1
|
118
122
|
* http://blog.evanweaver.com/articles/2007/07/09/ultrasphinx-searching-the-world-in-231-seconds
|
data/examples/default.base
CHANGED
@@ -53,9 +53,8 @@ client
|
|
53
53
|
source
|
54
54
|
{
|
55
55
|
# Individual SQL source options
|
56
|
+
sql_ranged_throttle = 0
|
56
57
|
sql_range_step = 5000
|
57
|
-
strip_html = 0
|
58
|
-
index_html_attrs =
|
59
58
|
sql_query_post =
|
60
59
|
}
|
61
60
|
|
@@ -67,6 +66,10 @@ index
|
|
67
66
|
morphology = stem_en
|
68
67
|
stopwords = # /path/to/stopwords.txt
|
69
68
|
min_word_len = 1
|
69
|
+
|
70
|
+
# HTML-specific options
|
71
|
+
html_strip = 0
|
72
|
+
html_index_attrs =
|
70
73
|
|
71
74
|
# Enable these if you need wildcard searching. They will slow down indexing significantly.
|
72
75
|
# min_infix_len = 1
|
@@ -14,12 +14,13 @@ module Ultrasphinx
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def get_association_model(klass, entry)
|
17
|
-
get_association(klass, entry)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
association = get_association(klass, entry)
|
18
|
+
if association
|
19
|
+
association.class_name.constantize
|
20
|
+
else
|
21
|
+
entry['class_name'].constantize
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
24
25
|
end
|
25
26
|
end
|
@@ -185,7 +185,7 @@ module Ultrasphinx
|
|
185
185
|
|
186
186
|
def build_regular_fields(klass, fields, entries, column_strings, join_strings, group_bys, remaining_columns)
|
187
187
|
entries.to_a.each do |entry|
|
188
|
-
source_string = "#{entry['
|
188
|
+
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
189
189
|
group_bys << source_string
|
190
190
|
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
191
191
|
end
|
@@ -207,17 +207,17 @@ module Ultrasphinx
|
|
207
207
|
raise ConfigurationError, "Unknown association from #{klass} to #{entry['class_name'] || entry['association_name']}" if not association and not entry['association_sql']
|
208
208
|
|
209
209
|
join_strings = install_join_unless_association_sql(entry['association_sql'], nil, join_strings) do
|
210
|
-
"LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['
|
210
|
+
"LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['table_alias']} ON " +
|
211
211
|
if (macro = association.macro) == :belongs_to
|
212
|
-
"#{entry['
|
212
|
+
"#{entry['table_alias']}.#{join_klass.primary_key} = #{klass.table_name}.#{association.primary_key_name}"
|
213
213
|
elsif macro == :has_one
|
214
|
-
"#{klass.table_name}.#{klass.primary_key} = #{entry['
|
214
|
+
"#{klass.table_name}.#{klass.primary_key} = #{entry['table_alias']}.#{association.primary_key_name}"
|
215
215
|
else
|
216
216
|
raise ConfigurationError, "Unidentified association macro #{macro.inspect}. Please use the :association_sql key to manually specify the JOIN syntax."
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
-
source_string = "#{entry['
|
220
|
+
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
221
221
|
group_bys << source_string
|
222
222
|
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
223
223
|
end
|
@@ -228,7 +228,7 @@ module Ultrasphinx
|
|
228
228
|
|
229
229
|
def build_concatenations(klass, fields, entries, column_strings, join_strings, group_bys, use_distinct, remaining_columns)
|
230
230
|
entries.to_a.each do |entry|
|
231
|
-
if
|
231
|
+
if entry['field']
|
232
232
|
# Group concats
|
233
233
|
|
234
234
|
# Only has_many's or explicit sql right now
|
@@ -241,11 +241,11 @@ module Ultrasphinx
|
|
241
241
|
join_strings = install_join_unless_association_sql(entry['association_sql'], nil, join_strings) do
|
242
242
|
# XXX make sure foreign key is right for polymorphic relationships
|
243
243
|
association = get_association(klass, entry)
|
244
|
-
"LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['
|
244
|
+
"LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['table_alias']} ON #{klass.table_name}.#{klass.primary_key} = #{entry['table_alias']}.#{association.primary_key_name}" +
|
245
245
|
(entry['conditions'] ? " AND (#{entry['conditions']})" : "")
|
246
246
|
end
|
247
247
|
|
248
|
-
source_string = "#{entry['
|
248
|
+
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
249
249
|
# We are using the field in an aggregate, so we don't want to add it to group_bys
|
250
250
|
source_string = SQL_FUNCTIONS[ADAPTER]['group_concat']._interpolate(source_string)
|
251
251
|
use_distinct = true
|
@@ -255,7 +255,7 @@ module Ultrasphinx
|
|
255
255
|
elsif entry['fields']
|
256
256
|
# Regular concats
|
257
257
|
source_string = "CONCAT_WS(' ', " + entry['fields'].map do |subfield|
|
258
|
-
"#{entry['
|
258
|
+
"#{entry['table_alias']}.#{subfield}"
|
259
259
|
end.each do |subsource_string|
|
260
260
|
group_bys << subsource_string
|
261
261
|
end.join(', ') + ")"
|
@@ -290,7 +290,7 @@ module Ultrasphinx
|
|
290
290
|
|
291
291
|
# Generate hashed integer fields for text grouping
|
292
292
|
if with_facet
|
293
|
-
column_strings << "
|
293
|
+
column_strings << "#{SQL_FUNCTIONS[ADAPTER]['hash']._interpolate(source_string)} AS #{as}_facet"
|
294
294
|
remaining_columns.delete("#{as}_facet")
|
295
295
|
end
|
296
296
|
[column_strings, remaining_columns]
|
@@ -56,7 +56,18 @@ class Hash
|
|
56
56
|
end.join("\n")
|
57
57
|
section ? "#{section} {\n#{inner}\n}\n" : inner
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
|
+
unless Hash.new.respond_to? :except
|
61
|
+
# Rails 1.2.6 compatibility
|
62
|
+
def except(*keys)
|
63
|
+
rejected = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
|
64
|
+
reject { |key,| rejected.include?(key) }
|
65
|
+
end
|
66
|
+
def except!(*keys)
|
67
|
+
replace(except(*keys))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
60
71
|
end
|
61
72
|
|
62
73
|
### Filter type coercion methods
|
data/lib/ultrasphinx/fields.rb
CHANGED
@@ -17,7 +17,7 @@ This is a special singleton configuration class that stores the index field conf
|
|
17
17
|
'datetime' => 'date',
|
18
18
|
'timestamp' => 'date',
|
19
19
|
'float' => 'float',
|
20
|
-
'boolean' => '
|
20
|
+
'boolean' => 'bool'
|
21
21
|
}
|
22
22
|
|
23
23
|
attr_accessor :classes, :types
|
@@ -49,12 +49,16 @@ This is a special singleton configuration class that stores the index field conf
|
|
49
49
|
classes[field] = [klass]
|
50
50
|
|
51
51
|
@groups << case new_type
|
52
|
-
when '
|
53
|
-
"
|
52
|
+
when 'integer'
|
53
|
+
"sql_attr_uint = #{field}"
|
54
|
+
when 'float'
|
55
|
+
"sql_attr_float = #{field}"
|
56
|
+
when 'bool'
|
57
|
+
"sql_attr_bool = #{field}"
|
54
58
|
when 'date'
|
55
|
-
"
|
59
|
+
"sql_attr_timestamp = #{field}"
|
56
60
|
when 'text'
|
57
|
-
"
|
61
|
+
"sql_attr_str2ordinal = #{field}" if string_sortable
|
58
62
|
end
|
59
63
|
end
|
60
64
|
end
|
@@ -73,7 +77,7 @@ This is a special singleton configuration class that stores the index field conf
|
|
73
77
|
case types[field]
|
74
78
|
when 'text'
|
75
79
|
"''"
|
76
|
-
when 'integer', 'float'
|
80
|
+
when 'integer', 'float', 'bool'
|
77
81
|
"0"
|
78
82
|
when 'date'
|
79
83
|
"18000" # Midnight on 1/1/1970
|
@@ -152,14 +156,20 @@ This is a special singleton configuration class that stores the index field conf
|
|
152
156
|
end
|
153
157
|
|
154
158
|
def extract_table_alias!(entry, klass)
|
155
|
-
unless entry['
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
159
|
+
unless entry['table_alias']
|
160
|
+
entry['table_alias'] = if entry['field'] and entry['field'].include? "." and entry['association_sql']
|
161
|
+
# This field is referenced by a table alias in association_sql
|
162
|
+
table_alias, entry['field'] = entry['field'].split(".")
|
163
|
+
table_alias
|
164
|
+
elsif get_association(klass, entry)
|
165
|
+
# Refers to the association
|
166
|
+
get_association(klass, entry).name
|
167
|
+
elsif entry['association_sql']
|
168
|
+
# Refers to the association_sql class's table
|
169
|
+
entry['class_name'].constantize.table_name
|
160
170
|
else
|
161
|
-
|
162
|
-
|
171
|
+
# Refers to this class
|
172
|
+
klass.table_name
|
163
173
|
end
|
164
174
|
end
|
165
175
|
end
|
@@ -117,7 +117,7 @@ Note how setting the <tt>:conditions</tt> on Comment is enough to configure a po
|
|
117
117
|
|
118
118
|
== Association scoping
|
119
119
|
|
120
|
-
A common use case is to only search records that belong to a particular parent model. Ultrasphinx configures Sphinx to support a <tt>:
|
120
|
+
A common use case is to only search records that belong to a particular parent model. Ultrasphinx configures Sphinx to support a <tt>:filters</tt> element on any date or numeric field, so any <tt>*_id</tt> fields you have will be filterable.
|
121
121
|
|
122
122
|
For example, say a Company <tt>has_many :users</tt> and each User <tt>has_many :articles</tt>. If you want to to filter Articles by Company, add <tt>company_id</tt> to the Article's <tt>is_indexed</tt> method. The best way is to grab it from the User association:
|
123
123
|
|
@@ -128,7 +128,7 @@ For example, say a Company <tt>has_many :users</tt> and each User <tt>has_many :
|
|
128
128
|
Now you can run:
|
129
129
|
|
130
130
|
@search = Ultrasphinx::Search.new('something',
|
131
|
-
:
|
131
|
+
:filters => {'company_id' => 493})
|
132
132
|
|
133
133
|
If the associations weren't just <tt>has_many</tt> and <tt>belongs_to</tt>, you would need to use the <tt>:association_sql</tt> key to set up a custom JOIN.
|
134
134
|
|
@@ -2,6 +2,14 @@
|
|
2
2
|
/* Fake CRC32 */
|
3
3
|
|
4
4
|
CREATE OR REPLACE FUNCTION crc32(text)
|
5
|
-
RETURNS
|
6
|
-
|
7
|
-
|
5
|
+
RETURNS bigint AS $$
|
6
|
+
DECLARE
|
7
|
+
tmp bigint;
|
8
|
+
BEGIN
|
9
|
+
tmp = (hex_to_int(SUBSTRING(MD5($1) FROM 1 FOR 8))::bigint);
|
10
|
+
IF tmp < 0 THEN
|
11
|
+
tmp = 4294967296 + tmp;
|
12
|
+
END IF;
|
13
|
+
return tmp;
|
14
|
+
END
|
15
|
+
$$ IMMUTABLE STRICT LANGUAGE plpgsql;
|
data/lib/ultrasphinx/search.rb
CHANGED
@@ -319,7 +319,8 @@ Note that your database is never changed by anything Ultrasphinx does.
|
|
319
319
|
|
320
320
|
|
321
321
|
# Overwrite the configured content accessors with excerpted and highlighted versions of themselves.
|
322
|
-
# Runs run if it hasn't already been done.
|
322
|
+
# Runs run if it hasn't already been done. Please note that this does not change the @attributes
|
323
|
+
# hash in the record; only the accessor.
|
323
324
|
def excerpt
|
324
325
|
|
325
326
|
require_run
|
@@ -356,7 +357,7 @@ Note that your database is never changed by anything Ultrasphinx does.
|
|
356
357
|
responses = responses.in_groups_of(Ultrasphinx::Search.excerpting_options['content_methods'].size)
|
357
358
|
|
358
359
|
results_with_content_methods.each_with_index do |result_and_methods, i|
|
359
|
-
#
|
360
|
+
# Override the individual model accessors with the excerpted data
|
360
361
|
result, methods = result_and_methods
|
361
362
|
methods.each_with_index do |method, j|
|
362
363
|
result._metaclass.send('define_method', method) { responses[i][j] } if method
|
@@ -61,12 +61,16 @@ module Ultrasphinx
|
|
61
61
|
# XXX We should coerce based on the Field values, not on the class
|
62
62
|
Array(opts['filters']).each do |field, value|
|
63
63
|
field = field.to_s
|
64
|
-
|
64
|
+
type = Fields.instance.types[field]
|
65
|
+
unless type
|
65
66
|
raise UsageError, "field #{field.inspect} is invalid"
|
66
67
|
end
|
68
|
+
|
67
69
|
begin
|
68
70
|
case value
|
69
71
|
when Integer, Float, BigDecimal, NilClass, Array
|
72
|
+
# XXX Hack to force floats to be floats
|
73
|
+
value = value.to_f if type == 'float'
|
70
74
|
# Just bomb the filter in there
|
71
75
|
request.filters << Riddle::Client::Filter.new(field, Array(value), false)
|
72
76
|
when Range
|
@@ -74,6 +78,8 @@ module Ultrasphinx
|
|
74
78
|
min, max = [value.begin, value.end].map {|x| x._to_numeric }
|
75
79
|
raise NoMethodError unless min <=> max and max <=> min
|
76
80
|
min, max = max, min if min > max
|
81
|
+
# XXX Hack to force floats to be floats
|
82
|
+
min, max = min.to_f, max.to_f if type == 'float'
|
77
83
|
request.filters << Riddle::Client::Filter.new(field, min..max, false)
|
78
84
|
when String
|
79
85
|
# XXX Hack to move text filters into the query
|
@@ -185,17 +191,24 @@ module Ultrasphinx
|
|
185
191
|
when 'fields'
|
186
192
|
[configuration['field'], ""]
|
187
193
|
when 'include'
|
188
|
-
association_model = get_association_model(klass, configuration)
|
189
194
|
# XXX Only handles the basic case. No test coverage.
|
190
|
-
|
191
|
-
|
195
|
+
|
196
|
+
table_alias = configuration['table_alias']
|
197
|
+
association_model = if configuration['class_name']
|
198
|
+
configuration['class_name'].constantize
|
199
|
+
else
|
200
|
+
get_association_model(klass, configuration)
|
201
|
+
end
|
202
|
+
|
203
|
+
["table_alias.#{configuration['field']}",
|
204
|
+
(configuration['association_sql'] or "LEFT OUTER JOIN #{association_model.table_name} AS table_alias ON table_alias.#{association_model.primary_key} = #{klass.table_name}.#{association_model.class_name.underscore}_id")
|
192
205
|
]
|
193
206
|
when 'concatenate'
|
194
207
|
# Wait for someone to complain before worrying about this
|
195
208
|
raise "Concatenation text facets have not been implemented"
|
196
209
|
end
|
197
210
|
|
198
|
-
klass.connection.execute("SELECT #{field_string} AS value,
|
211
|
+
klass.connection.execute("SELECT #{field_string} AS value, #{SQL_FUNCTIONS[ADAPTER]['hash']._interpolate(field_string)} AS hash FROM #{klass.table_name} #{join_string} GROUP BY value").each do |value, hash|
|
199
212
|
FACET_CACHE[facet][hash.to_i] = value
|
200
213
|
end
|
201
214
|
klass
|
@@ -59,12 +59,14 @@ module Ultrasphinx
|
|
59
59
|
SQL_FUNCTIONS = {
|
60
60
|
'mysql' => {
|
61
61
|
'group_concat' => "CAST(GROUP_CONCAT(DISTINCT ? SEPARATOR ' ') AS CHAR)",
|
62
|
+
'hash' => "CAST(CRC32(?) AS unsigned)",
|
62
63
|
'range_cast' => "?",
|
63
64
|
'stored_procedures' => {}
|
64
65
|
},
|
65
66
|
'postgresql' => {
|
66
67
|
'group_concat' => "GROUP_CONCAT(?)",
|
67
68
|
'range_cast' => "cast(coalesce(?,1) AS integer)",
|
69
|
+
'hash' => "CRC32(?)",
|
68
70
|
'stored_procedures' => Hash[*(
|
69
71
|
['hex_to_int', 'group_concat', 'concat_ws', 'unix_timestamp', 'crc32'].map do |name|
|
70
72
|
[name, load_stored_procedure(name)]
|
data/tasks/ultrasphinx.rake
CHANGED
@@ -25,7 +25,7 @@ namespace :ultrasphinx do
|
|
25
25
|
rotate = ultrasphinx_daemon_running?
|
26
26
|
mkdir_p Ultrasphinx::INDEX_SETTINGS['path']
|
27
27
|
|
28
|
-
cmd = "indexer --config #{Ultrasphinx::CONF_PATH}"
|
28
|
+
cmd = "indexer --config '#{Ultrasphinx::CONF_PATH}'"
|
29
29
|
cmd << " #{ENV['OPTS']} " if ENV['OPTS']
|
30
30
|
cmd << " --rotate" if rotate
|
31
31
|
cmd << " #{Ultrasphinx::UNIFIED_INDEX_NAME}"
|
@@ -51,7 +51,7 @@ namespace :ultrasphinx do
|
|
51
51
|
task :start => [:_environment] do
|
52
52
|
FileUtils.mkdir_p File.dirname(Ultrasphinx::DAEMON_SETTINGS["log"]) rescue nil
|
53
53
|
raise Ultrasphinx::DaemonError, "Already running" if ultrasphinx_daemon_running?
|
54
|
-
system "searchd --config #{Ultrasphinx::CONF_PATH}"
|
54
|
+
system "searchd --config '#{Ultrasphinx::CONF_PATH}'"
|
55
55
|
sleep(4) # give daemon a chance to write the pid file
|
56
56
|
if ultrasphinx_daemon_running?
|
57
57
|
say "started successfully"
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
|
-
has_one :
|
2
|
+
has_one :specific_seller, :class_name => "Seller"
|
3
3
|
has_one :address, :class_name => "Geo::Address"
|
4
4
|
|
5
5
|
is_indexed :fields => ['login', 'email', 'deleted'],
|
6
|
-
:include => [{:
|
6
|
+
:include => [{:association_name => 'specific_seller', :field => 'company_name', :as => 'company'},
|
7
7
|
{:class_name => 'Seller', :field => 'sellers_two.company_name', :as => 'company_two', 'association_sql' => 'LEFT OUTER JOIN sellers AS sellers_two ON users.id = sellers_two.user_id', 'function_sql' => "REPLACE(?, '6', ' replacement ')"}],
|
8
8
|
:conditions => "deleted = '0'"
|
9
9
|
|
@@ -55,8 +55,10 @@ module Rails
|
|
55
55
|
|
56
56
|
def load_rails_gem
|
57
57
|
if version = self.class.gem_version
|
58
|
+
STDERR.puts "Boot.rb loading version #{version}"
|
58
59
|
gem 'rails', version
|
59
60
|
else
|
61
|
+
STDERR.puts "Boot.rb loading latest available version"
|
60
62
|
gem 'rails'
|
61
63
|
end
|
62
64
|
rescue Gem::LoadError => load_error
|
@@ -1,11 +1,12 @@
|
|
1
1
|
|
2
|
-
RAILS_GEM_VERSION = ENV['MULTIRAILS_RAILS_VERSION'] if ENV['MULTIRAILS_RAILS_VERSION']
|
3
|
-
|
4
2
|
require File.join(File.dirname(__FILE__), 'boot')
|
5
3
|
require 'action_controller'
|
6
4
|
|
7
5
|
Rails::Initializer.run do |config|
|
8
|
-
|
6
|
+
if ActionController::Base.respond_to? 'session='
|
7
|
+
config.action_controller.session = {:session_key => '_app_session', :secret => '22cde4d5c1a61ba69a81795322cde4d5c1a61ba69a817953'}
|
8
|
+
end
|
9
|
+
|
9
10
|
config.load_paths << "#{RAILS_ROOT}/app/models/person" # moduleless model path
|
10
11
|
end
|
11
12
|
|
@@ -1,8 +1,22 @@
|
|
1
|
+
|
1
2
|
#
|
2
3
|
# Sphinx/Ultrasphinx user-configurable options.
|
3
4
|
#
|
4
|
-
# Copy this file to RAILS_ROOT/config/ultrasphinx.
|
5
|
-
#
|
5
|
+
# Copy this file to RAILS_ROOT/config/ultrasphinx. You can use individual
|
6
|
+
# namespaces if you want (e.g. development.base, production.base,
|
7
|
+
# test.base).
|
8
|
+
#
|
9
|
+
# This file should not be handed directly to Sphinx. Use the rake task
|
10
|
+
#
|
11
|
+
# rake ultrasphinx::configure
|
12
|
+
#
|
13
|
+
# to generate a parallel default.conf file. This is the file that Sphinx itself will
|
14
|
+
# use. The Ultrasphinx rake tasks automatically pass the correct file to
|
15
|
+
# to Sphinx.
|
16
|
+
#
|
17
|
+
# It is safe to edit .base files by hand. It is not safe to edit the generated
|
18
|
+
# .conf files. Do not symlink the .conf file to the .base file! I don't know why
|
19
|
+
# people think they need to do that. It's wrong.
|
6
20
|
#
|
7
21
|
|
8
22
|
indexer
|
@@ -16,7 +30,8 @@ searchd
|
|
16
30
|
# Daemon options
|
17
31
|
# What interface the search daemon should listen on and where to store its logs
|
18
32
|
address = 0.0.0.0
|
19
|
-
port =
|
33
|
+
port = 3312
|
34
|
+
seamless_rotate = 1
|
20
35
|
log = /tmp/sphinx/searchd.log
|
21
36
|
query_log = /tmp/sphinx/query.log
|
22
37
|
read_timeout = 5
|
@@ -28,29 +43,38 @@ searchd
|
|
28
43
|
client
|
29
44
|
{
|
30
45
|
# Client options
|
31
|
-
|
46
|
+
# Name of the Aspell dictionary (two letters max)
|
47
|
+
dictionary_name = ap
|
32
48
|
# How your application connects to the search daemon (not necessarily the same as above)
|
33
49
|
server_host = localhost
|
34
|
-
server_port =
|
50
|
+
server_port = 3312
|
35
51
|
}
|
36
52
|
|
37
53
|
source
|
38
54
|
{
|
39
55
|
# Individual SQL source options
|
40
|
-
|
41
|
-
|
42
|
-
index_html_attrs =
|
56
|
+
sql_ranged_throttle = 0
|
57
|
+
sql_range_step = 5000
|
43
58
|
sql_query_post =
|
44
59
|
}
|
45
60
|
|
46
61
|
index
|
47
62
|
{
|
48
63
|
# Index building options
|
49
|
-
path = /tmp/sphinx
|
64
|
+
path = /tmp/sphinx
|
50
65
|
docinfo = extern # just leave this alone
|
51
66
|
morphology = stem_en
|
52
67
|
stopwords = # /path/to/stopwords.txt
|
53
68
|
min_word_len = 1
|
69
|
+
|
70
|
+
# HTML-specific options
|
71
|
+
html_strip = 0
|
72
|
+
html_index_attrs =
|
73
|
+
|
74
|
+
# Enable these if you need wildcard searching. They will slow down indexing significantly.
|
75
|
+
# min_infix_len = 1
|
76
|
+
# enable_star = 1
|
77
|
+
|
54
78
|
charset_type = utf-8 # or sbcs (Single Byte Character Set)
|
55
79
|
charset_table = 0..9, A..Z->a..z, -, _, ., &, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, U+E5, U+C4->U+E4, U+E4, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, U+17e->z,
|
56
80
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
# Auto-generated at
|
2
|
+
# Auto-generated at Tue Feb 05 04:49:29 -0500 2008.
|
3
3
|
# Hand modifications will be overwritten.
|
4
4
|
# /Users/eweaver/Desktop/projects/chow/vendor/plugins/ultrasphinx/test/integration/app/config/ultrasphinx/default.base
|
5
5
|
indexer {
|
@@ -9,9 +9,10 @@ searchd {
|
|
9
9
|
read_timeout = 5
|
10
10
|
max_children = 300
|
11
11
|
log = /tmp/sphinx/searchd.log
|
12
|
-
port =
|
12
|
+
port = 3312
|
13
13
|
max_matches = 100000
|
14
14
|
query_log = /tmp/sphinx/query.log
|
15
|
+
seamless_rotate = 1
|
15
16
|
pid_file = /tmp/sphinx/searchd.pid
|
16
17
|
address = 0.0.0.0
|
17
18
|
}
|
@@ -20,10 +21,9 @@ searchd {
|
|
20
21
|
|
21
22
|
source geo__states
|
22
23
|
{
|
23
|
-
|
24
|
-
sql_range_step = 20000
|
25
|
-
index_html_attrs =
|
24
|
+
sql_range_step = 5000
|
26
25
|
sql_query_post =
|
26
|
+
sql_ranged_throttle = 0
|
27
27
|
|
28
28
|
type = mysql
|
29
29
|
sql_query_pre = SET SESSION group_concat_max_len = 65535
|
@@ -36,13 +36,13 @@ sql_user = root
|
|
36
36
|
sql_query_range = SELECT MIN(id) , MAX(id) FROM states
|
37
37
|
sql_query = SELECT (states.id * 5 + 0) AS id, CAST(GROUP_CONCAT(DISTINCT addresses.name SEPARATOR ' ') AS CHAR) AS address_name, 0 AS capitalization, 'Geo::State' AS class, 0 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM states LEFT OUTER JOIN addresses AS addresses ON states.id = addresses.state_id WHERE states.id >= $start AND states.id <= $end GROUP BY states.id
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
sql_attr_float = capitalization
|
40
|
+
sql_attr_uint = class_id
|
41
|
+
sql_attr_uint = company_name_facet
|
42
|
+
sql_attr_timestamp = created_at
|
43
|
+
sql_attr_bool = deleted
|
44
|
+
sql_attr_str2ordinal = mission_statement
|
45
|
+
sql_attr_uint = user_id
|
46
46
|
sql_query_info = SELECT * FROM states WHERE states.id = (($id - 0) / 5)
|
47
47
|
}
|
48
48
|
|
@@ -51,10 +51,9 @@ sql_query_info = SELECT * FROM states WHERE states.id = (($id - 0) / 5)
|
|
51
51
|
|
52
52
|
source sellers
|
53
53
|
{
|
54
|
-
|
55
|
-
sql_range_step = 20000
|
56
|
-
index_html_attrs =
|
54
|
+
sql_range_step = 5000
|
57
55
|
sql_query_post =
|
56
|
+
sql_ranged_throttle = 0
|
58
57
|
|
59
58
|
type = mysql
|
60
59
|
sql_query_pre = SET SESSION group_concat_max_len = 65535
|
@@ -65,15 +64,15 @@ sql_host = localhost
|
|
65
64
|
sql_pass =
|
66
65
|
sql_user = root
|
67
66
|
sql_query_range = SELECT MIN(id) , MAX(id) FROM sellers
|
68
|
-
sql_query = SELECT (sellers.id * 5 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CRC32(sellers.company_name) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY sellers.id
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
67
|
+
sql_query = SELECT (sellers.id * 5 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CAST(CRC32(sellers.company_name) AS unsigned) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY sellers.id
|
68
|
+
|
69
|
+
sql_attr_float = capitalization
|
70
|
+
sql_attr_uint = class_id
|
71
|
+
sql_attr_uint = company_name_facet
|
72
|
+
sql_attr_timestamp = created_at
|
73
|
+
sql_attr_bool = deleted
|
74
|
+
sql_attr_str2ordinal = mission_statement
|
75
|
+
sql_attr_uint = user_id
|
77
76
|
sql_query_info = SELECT * FROM sellers WHERE sellers.id = (($id - 1) / 5)
|
78
77
|
}
|
79
78
|
|
@@ -82,10 +81,9 @@ sql_query_info = SELECT * FROM sellers WHERE sellers.id = (($id - 1) / 5)
|
|
82
81
|
|
83
82
|
source geo__addresses
|
84
83
|
{
|
85
|
-
|
86
|
-
sql_range_step = 20000
|
87
|
-
index_html_attrs =
|
84
|
+
sql_range_step = 5000
|
88
85
|
sql_query_post =
|
86
|
+
sql_ranged_throttle = 0
|
89
87
|
|
90
88
|
type = mysql
|
91
89
|
sql_query_pre = SET SESSION group_concat_max_len = 65535
|
@@ -96,15 +94,15 @@ sql_host = localhost
|
|
96
94
|
sql_pass =
|
97
95
|
sql_user = root
|
98
96
|
sql_query_range = SELECT MIN(id) , MAX(id) FROM addresses
|
99
|
-
sql_query = SELECT (addresses.id * 5 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, addresses.name AS name,
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
97
|
+
sql_query = SELECT (addresses.id * 5 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, addresses.name AS name, state.name AS state, 0 AS user_id FROM addresses LEFT OUTER JOIN states AS state ON state.id = addresses.state_id WHERE addresses.id >= $start AND addresses.id <= $end GROUP BY addresses.id
|
98
|
+
|
99
|
+
sql_attr_float = capitalization
|
100
|
+
sql_attr_uint = class_id
|
101
|
+
sql_attr_uint = company_name_facet
|
102
|
+
sql_attr_timestamp = created_at
|
103
|
+
sql_attr_bool = deleted
|
104
|
+
sql_attr_str2ordinal = mission_statement
|
105
|
+
sql_attr_uint = user_id
|
108
106
|
sql_query_info = SELECT * FROM addresses WHERE addresses.id = (($id - 2) / 5)
|
109
107
|
}
|
110
108
|
|
@@ -113,10 +111,9 @@ sql_query_info = SELECT * FROM addresses WHERE addresses.id = (($id - 2) / 5)
|
|
113
111
|
|
114
112
|
source users
|
115
113
|
{
|
116
|
-
|
117
|
-
sql_range_step = 20000
|
118
|
-
index_html_attrs =
|
114
|
+
sql_range_step = 5000
|
119
115
|
sql_query_post =
|
116
|
+
sql_ranged_throttle = 0
|
120
117
|
|
121
118
|
type = mysql
|
122
119
|
sql_query_pre = SET SESSION group_concat_max_len = 65535
|
@@ -127,15 +124,15 @@ sql_host = localhost
|
|
127
124
|
sql_pass =
|
128
125
|
sql_user = root
|
129
126
|
sql_query_range = SELECT MIN(id) , MAX(id) FROM users
|
130
|
-
sql_query = SELECT (users.id * 5 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id,
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
127
|
+
sql_query = SELECT (users.id * 5 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id, specific_seller.company_name AS company, '' AS company_name, 0 AS company_name_facet, REPLACE(sellers_two.company_name, '6', ' replacement ') AS company_two, '' AS content, 18000 AS created_at, users.deleted AS deleted, users.email AS email, users.login AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM users LEFT OUTER JOIN sellers AS specific_seller ON users.id = specific_seller.user_id LEFT OUTER JOIN sellers AS sellers_two ON users.id = sellers_two.user_id WHERE users.id >= $start AND users.id <= $end AND (deleted = '0') GROUP BY users.id
|
128
|
+
|
129
|
+
sql_attr_float = capitalization
|
130
|
+
sql_attr_uint = class_id
|
131
|
+
sql_attr_uint = company_name_facet
|
132
|
+
sql_attr_timestamp = created_at
|
133
|
+
sql_attr_bool = deleted
|
134
|
+
sql_attr_str2ordinal = mission_statement
|
135
|
+
sql_attr_uint = user_id
|
139
136
|
sql_query_info = SELECT * FROM users WHERE users.id = (($id - 3) / 5)
|
140
137
|
}
|
141
138
|
|
@@ -144,10 +141,9 @@ sql_query_info = SELECT * FROM users WHERE users.id = (($id - 3) / 5)
|
|
144
141
|
|
145
142
|
source geo__countries
|
146
143
|
{
|
147
|
-
|
148
|
-
sql_range_step = 20000
|
149
|
-
index_html_attrs =
|
144
|
+
sql_range_step = 5000
|
150
145
|
sql_query_post =
|
146
|
+
sql_ranged_throttle = 0
|
151
147
|
|
152
148
|
type = mysql
|
153
149
|
sql_query_pre = SET SESSION group_concat_max_len = 65535
|
@@ -160,13 +156,13 @@ sql_user = root
|
|
160
156
|
sql_query_range = SELECT MIN(id) , MAX(id) FROM countries
|
161
157
|
sql_query = SELECT (countries.id * 5 + 4) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Country' AS class, 4 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, countries.name AS name, '' AS state, 0 AS user_id FROM countries WHERE countries.id >= $start AND countries.id <= $end GROUP BY countries.id
|
162
158
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
159
|
+
sql_attr_float = capitalization
|
160
|
+
sql_attr_uint = class_id
|
161
|
+
sql_attr_uint = company_name_facet
|
162
|
+
sql_attr_timestamp = created_at
|
163
|
+
sql_attr_bool = deleted
|
164
|
+
sql_attr_str2ordinal = mission_statement
|
165
|
+
sql_attr_uint = user_id
|
170
166
|
sql_query_info = SELECT * FROM countries WHERE countries.id = (($id - 4) / 5)
|
171
167
|
}
|
172
168
|
|
@@ -181,11 +177,15 @@ index complete
|
|
181
177
|
source = sellers
|
182
178
|
source = users
|
183
179
|
charset_type = utf-8
|
180
|
+
html_index_attrs =
|
184
181
|
charset_table = 0..9, A..Z->a..z, -, _, ., &, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, U+E5, U+C4->U+E4, U+E4, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, U+17e->z,
|
185
182
|
min_word_len = 1
|
183
|
+
# enable_star = 1
|
186
184
|
stopwords =
|
185
|
+
html_strip = 0
|
187
186
|
path = /tmp/sphinx//sphinx_index_complete
|
188
187
|
docinfo = extern
|
189
188
|
morphology = stem_en
|
189
|
+
# min_infix_len = 1
|
190
190
|
}
|
191
191
|
|
@@ -205,9 +205,11 @@ class SearchTest < Test::Unit::TestCase
|
|
205
205
|
end
|
206
206
|
|
207
207
|
def test_text_facet
|
208
|
-
# XXX Still broken on Postgres
|
209
208
|
@s = Ultrasphinx::Search.new(:facets => ['company_name']).run
|
210
|
-
assert_equal
|
209
|
+
assert_equal(
|
210
|
+
(Seller.count + 1),
|
211
|
+
@s.facets['company_name'].size
|
212
|
+
)
|
211
213
|
end
|
212
214
|
|
213
215
|
def test_numeric_facet
|
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
|
2
2
|
require 'rubygems'
|
3
3
|
require 'test/unit'
|
4
|
-
require '
|
4
|
+
require 'echoe'
|
5
5
|
require 'multi_rails_init'
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
if defined? ENV['MULTIRAILS_RAILS_VERSION']
|
8
|
+
ENV['RAILS_GEM_VERSION'] = ENV['MULTIRAILS_RAILS_VERSION']
|
9
|
+
end
|
10
|
+
|
11
|
+
Echoe.silence do
|
12
|
+
HERE = File.expand_path(File.dirname(__FILE__))
|
13
|
+
$LOAD_PATH << HERE
|
14
|
+
LOG = "#{HERE}/integration/app/log/development.log"
|
15
|
+
end
|
9
16
|
|
10
17
|
require 'integration/app/config/environment'
|
11
18
|
|
data/ultrasphinx.gemspec
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Ultrasphinx-1.
|
2
|
+
# Gem::Specification for Ultrasphinx-1.8
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{ultrasphinx}
|
7
|
-
s.version = "1.
|
7
|
+
s.version = "1.8"
|
8
8
|
|
9
9
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = [""]
|
13
|
-
s.date = %q{2008-
|
13
|
+
s.date = %q{2008-02-05}
|
14
14
|
s.description = %q{Ruby on Rails configurator and client to the Sphinx fulltext search engine.}
|
15
15
|
s.email = %q{}
|
16
16
|
s.files = ["CHANGELOG", "DEPLOYMENT_NOTES", "examples/ap.multi", "examples/default.base", "init.rb", "lib/ultrasphinx/associations.rb", "lib/ultrasphinx/autoload.rb", "lib/ultrasphinx/configure.rb", "lib/ultrasphinx/core_extensions.rb", "lib/ultrasphinx/fields.rb", "lib/ultrasphinx/is_indexed.rb", "lib/ultrasphinx/postgresql/concat_ws.sql", "lib/ultrasphinx/postgresql/crc32.sql", "lib/ultrasphinx/postgresql/group_concat.sql", "lib/ultrasphinx/postgresql/hex_to_int.sql", "lib/ultrasphinx/postgresql/language.sql", "lib/ultrasphinx/postgresql/unix_timestamp.sql", "lib/ultrasphinx/search/internals.rb", "lib/ultrasphinx/search/parser.rb", "lib/ultrasphinx/search.rb", "lib/ultrasphinx/spell.rb", "lib/ultrasphinx/ultrasphinx.rb", "lib/ultrasphinx.rb", "LICENSE", "Manifest", "RAKE_TASKS", "README", "tasks/ultrasphinx.rake", "test/config/ultrasphinx/test.base", "test/integration/app/app/controllers/addresses_controller.rb", "test/integration/app/app/controllers/application.rb", "test/integration/app/app/controllers/sellers_controller.rb", "test/integration/app/app/controllers/states_controller.rb", "test/integration/app/app/controllers/users_controller.rb", "test/integration/app/app/helpers/addresses_helper.rb", "test/integration/app/app/helpers/application_helper.rb", "test/integration/app/app/helpers/sellers_helper.rb", "test/integration/app/app/helpers/states_helper.rb", "test/integration/app/app/helpers/users_helper.rb", "test/integration/app/app/models/geo/address.rb", "test/integration/app/app/models/geo/country.rb", "test/integration/app/app/models/geo/state.rb", "test/integration/app/app/models/person/user.rb", "test/integration/app/app/models/seller.rb", "test/integration/app/app/views/addresses/edit.html.erb", "test/integration/app/app/views/addresses/index.html.erb", "test/integration/app/app/views/addresses/new.html.erb", "test/integration/app/app/views/addresses/show.html.erb", "test/integration/app/app/views/layouts/addresses.html.erb", "test/integration/app/app/views/layouts/sellers.html.erb", "test/integration/app/app/views/layouts/states.html.erb", "test/integration/app/app/views/layouts/users.html.erb", "test/integration/app/app/views/sellers/edit.html.erb", "test/integration/app/app/views/sellers/index.html.erb", "test/integration/app/app/views/sellers/new.html.erb", "test/integration/app/app/views/sellers/show.html.erb", "test/integration/app/app/views/states/edit.html.erb", "test/integration/app/app/views/states/index.html.erb", "test/integration/app/app/views/states/new.html.erb", "test/integration/app/app/views/states/show.html.erb", "test/integration/app/app/views/users/edit.html.erb", "test/integration/app/app/views/users/index.html.erb", "test/integration/app/app/views/users/new.html.erb", "test/integration/app/app/views/users/show.html.erb", "test/integration/app/config/boot.rb", "test/integration/app/config/database.yml", "test/integration/app/config/environment.rb", "test/integration/app/config/environments/development.rb", "test/integration/app/config/environments/production.rb", "test/integration/app/config/environments/test.rb", "test/integration/app/config/locomotive.yml", "test/integration/app/config/routes.rb", "test/integration/app/config/ultrasphinx/default.base", "test/integration/app/config/ultrasphinx/development.conf.canonical", "test/integration/app/db/migrate/001_create_users.rb", "test/integration/app/db/migrate/002_create_sellers.rb", "test/integration/app/db/migrate/003_create_addresses.rb", "test/integration/app/db/migrate/004_create_states.rb", "test/integration/app/db/migrate/005_add_capitalization_to_seller.rb", "test/integration/app/db/migrate/006_add_deleted_to_user.rb", "test/integration/app/db/migrate/007_add_lat_and_long_to_address.rb", "test/integration/app/db/migrate/008_add_mission_statement_to_seller.rb", "test/integration/app/db/migrate/009_create_countries.rb", "test/integration/app/doc/README_FOR_APP", "test/integration/app/public/404.html", "test/integration/app/public/500.html", "test/integration/app/public/dispatch.cgi", "test/integration/app/public/dispatch.fcgi", "test/integration/app/public/dispatch.rb", "test/integration/app/public/favicon.ico", "test/integration/app/public/images/rails.png", "test/integration/app/public/index.html", "test/integration/app/public/javascripts/application.js", "test/integration/app/public/javascripts/controls.js", "test/integration/app/public/javascripts/dragdrop.js", "test/integration/app/public/javascripts/effects.js", "test/integration/app/public/javascripts/prototype.js", "test/integration/app/public/robots.txt", "test/integration/app/public/stylesheets/scaffold.css", "test/integration/app/Rakefile", "test/integration/app/README", "test/integration/app/script/about", "test/integration/app/script/breakpointer", "test/integration/app/script/console", "test/integration/app/script/destroy", "test/integration/app/script/generate", "test/integration/app/script/performance/benchmarker", "test/integration/app/script/performance/profiler", "test/integration/app/script/plugin", "test/integration/app/script/process/inspector", "test/integration/app/script/process/reaper", "test/integration/app/script/process/spawner", "test/integration/app/script/runner", "test/integration/app/script/server", "test/integration/app/test/fixtures/addresses.yml", "test/integration/app/test/fixtures/countries.yml", "test/integration/app/test/fixtures/sellers.yml", "test/integration/app/test/fixtures/states.yml", "test/integration/app/test/fixtures/users.yml", "test/integration/app/test/functional/addresses_controller_test.rb", "test/integration/app/test/functional/sellers_controller_test.rb", "test/integration/app/test/functional/states_controller_test.rb", "test/integration/app/test/functional/users_controller_test.rb", "test/integration/app/test/test_helper.rb", "test/integration/app/test/unit/address_test.rb", "test/integration/app/test/unit/seller_test.rb", "test/integration/app/test/unit/state_test.rb", "test/integration/app/test/unit/user_test.rb", "test/integration/configure_test.rb", "test/integration/search_test.rb", "test/integration/server_test.rb", "test/integration/spell_test.rb", "test/setup.rb", "test/teardown.rb", "test/test_all.rb", "test/test_helper.rb", "test/ts.multi", "test/unit/parser_test.rb", "TODO", "vendor/riddle/lib/riddle/client/filter.rb", "vendor/riddle/lib/riddle/client/message.rb", "vendor/riddle/lib/riddle/client/response.rb", "vendor/riddle/lib/riddle/client.rb", "vendor/riddle/lib/riddle.rb", "vendor/riddle/MIT-LICENCE", "vendor/riddle/Rakefile", "vendor/riddle/README", "vendor/riddle/spec/fixtures/data/anchor.bin", "vendor/riddle/spec/fixtures/data/any.bin", "vendor/riddle/spec/fixtures/data/boolean.bin", "vendor/riddle/spec/fixtures/data/distinct.bin", "vendor/riddle/spec/fixtures/data/filter.bin", "vendor/riddle/spec/fixtures/data/filter_array.bin", "vendor/riddle/spec/fixtures/data/filter_array_exclude.bin", "vendor/riddle/spec/fixtures/data/filter_floats.bin", "vendor/riddle/spec/fixtures/data/filter_floats_exclude.bin", "vendor/riddle/spec/fixtures/data/filter_floats_range.bin", "vendor/riddle/spec/fixtures/data/filter_range.bin", "vendor/riddle/spec/fixtures/data/filter_range_exclude.bin", "vendor/riddle/spec/fixtures/data/group.bin", "vendor/riddle/spec/fixtures/data/index.bin", "vendor/riddle/spec/fixtures/data/phrase.bin", "vendor/riddle/spec/fixtures/data/simple.bin", "vendor/riddle/spec/fixtures/data/sort.bin", "vendor/riddle/spec/fixtures/data/update_simple.bin", "vendor/riddle/spec/fixtures/data/weights.bin", "vendor/riddle/spec/fixtures/sphinx/configuration.erb", "vendor/riddle/spec/fixtures/sql/conf.example.yml", "vendor/riddle/spec/fixtures/sql/data.sql", "vendor/riddle/spec/fixtures/sql/structure.sql", "vendor/riddle/spec/functional/excerpt_spec.rb", "vendor/riddle/spec/functional/search_spec.rb", "vendor/riddle/spec/functional/update_spec.rb", "vendor/riddle/spec/spec_helper.rb", "vendor/riddle/spec/sphinx_helper.rb", "vendor/riddle/spec/unit/client_spec.rb", "vendor/riddle/spec/unit/filter_spec.rb", "vendor/riddle/spec/unit/message_spec.rb", "vendor/riddle/spec/unit/response_spec.rb", "vendor/will_paginate/LICENSE", "ultrasphinx.gemspec"]
|
data/vendor/riddle/README
CHANGED
@@ -8,13 +8,13 @@ opting for a more Ruby-like structure.
|
|
8
8
|
While it doesn't (yet) exist as a gem, you can obtain the sourcecode via subversion. If you
|
9
9
|
are after a specific release, use the tag as follows:
|
10
10
|
|
11
|
-
svn co http://rails-oceania.googlecode.com/svn/patallan/riddle/tags/0.9.8-
|
11
|
+
svn co http://rails-oceania.googlecode.com/svn/patallan/riddle/tags/0.9.8-r1065 riddle
|
12
12
|
|
13
13
|
Or for the most current, just use trunk:
|
14
14
|
|
15
15
|
svn co http://rails-oceania.googlecode.com/svn/patallan/riddle/trunk riddle
|
16
16
|
|
17
|
-
Please note that at the time of writing, only 0.9.8r871, 0.9.8r909 and 0.9.
|
17
|
+
Please note that at the time of writing, only 0.9.8r871, 0.9.8r909, 0.9.8r985 and 0.9.8r1065 are supported.
|
18
18
|
|
19
19
|
To get started, just instantiate a Client object:
|
20
20
|
|
data/vendor/riddle/Rakefile
CHANGED
@@ -66,14 +66,11 @@ module RDoc
|
|
66
66
|
<div id="validator-badges">
|
67
67
|
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
68
68
|
</div>
|
69
|
-
<script type="text/javascript">
|
70
|
-
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
71
|
-
document.write("\\<script src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'>\\<\\/script>" );
|
69
|
+
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
72
70
|
</script>
|
73
71
|
<script type="text/javascript">
|
74
|
-
|
75
|
-
|
76
|
-
pageTracker._trackPageview();
|
72
|
+
_uacct = "%analytics%";
|
73
|
+
urchinTracker();
|
77
74
|
</script>
|
78
75
|
|
79
76
|
</body>
|
data/vendor/riddle/lib/riddle.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'socket'
|
1
2
|
require 'riddle/client'
|
2
3
|
require 'riddle/client/filter'
|
3
4
|
require 'riddle/client/message'
|
@@ -11,7 +12,7 @@ module Riddle #:nodoc:
|
|
11
12
|
Major = 0
|
12
13
|
Minor = 9
|
13
14
|
Tiny = 8
|
14
|
-
Rev =
|
15
|
+
Rev = 1065
|
15
16
|
|
16
17
|
String = [Major, Minor, Tiny].join('.') + "r#{Rev}"
|
17
18
|
end
|
@@ -32,9 +32,9 @@ module Riddle
|
|
32
32
|
}
|
33
33
|
|
34
34
|
Versions = {
|
35
|
-
:search =>
|
35
|
+
:search => 0x112, # VER_COMMAND_SEARCH
|
36
36
|
:excerpt => 0x100, # VER_COMMAND_EXCERPT
|
37
|
-
:update =>
|
37
|
+
:update => 0x101 # VER_COMMAND_UPDATE
|
38
38
|
}
|
39
39
|
|
40
40
|
Statuses = {
|
@@ -54,6 +54,12 @@ module Riddle
|
|
54
54
|
:extended2 => 6 # SPH_MATCH_EXTENDED2
|
55
55
|
}
|
56
56
|
|
57
|
+
RankModes = {
|
58
|
+
:proximity_bm25 => 0, # SPH_RANK_PROXIMITY_BM25
|
59
|
+
:bm25 => 1, # SPH_RANK_BM25
|
60
|
+
:none => 2 # SPH_RANK_NONE
|
61
|
+
}
|
62
|
+
|
57
63
|
SortModes = {
|
58
64
|
:relevance => 0, # SPH_SORT_RELEVANCE
|
59
65
|
:attr_desc => 1, # SPH_SORT_ATTR_DESC
|
@@ -89,7 +95,8 @@ module Riddle
|
|
89
95
|
attr_accessor :server, :port, :offset, :limit, :max_matches,
|
90
96
|
:match_mode, :sort_mode, :sort_by, :weights, :id_range, :filters,
|
91
97
|
:group_by, :group_function, :group_clause, :group_distinct, :cut_off,
|
92
|
-
:retry_count, :retry_delay, :anchor
|
98
|
+
:retry_count, :retry_delay, :anchor, :index_weights, :rank_mode,
|
99
|
+
:max_query_time, :field_weights
|
93
100
|
attr_reader :queue
|
94
101
|
|
95
102
|
# Can instantiate with a specific server and port - otherwise it assumes
|
@@ -119,6 +126,10 @@ module Riddle
|
|
119
126
|
@anchor = {}
|
120
127
|
# string keys are index names, integer values are weightings
|
121
128
|
@index_weights = {}
|
129
|
+
@rank_mode = :proximity_bm25
|
130
|
+
@max_query_time = 0
|
131
|
+
# string keys are field names, integer values are weightings
|
132
|
+
@field_weights = {}
|
122
133
|
|
123
134
|
@queue = []
|
124
135
|
end
|
@@ -181,7 +192,7 @@ module Riddle
|
|
181
192
|
matches = response.next_int
|
182
193
|
is_64_bit = response.next_int
|
183
194
|
for i in 0...matches
|
184
|
-
doc = is_64_bit > 0 ?
|
195
|
+
doc = is_64_bit > 0 ? response.next_64bit_int : response.next_int
|
185
196
|
weight = response.next_int
|
186
197
|
|
187
198
|
result[:matches] << {:doc => doc, :weight => weight, :index => i, :attributes => {}}
|
@@ -344,7 +355,7 @@ module Riddle
|
|
344
355
|
version = 0
|
345
356
|
length = 0
|
346
357
|
message = Array(messages).join("")
|
347
|
-
|
358
|
+
|
348
359
|
connect do |socket|
|
349
360
|
case command
|
350
361
|
when :search
|
@@ -397,7 +408,8 @@ module Riddle
|
|
397
408
|
message = Message.new
|
398
409
|
|
399
410
|
# Mode, Limits, Sort Mode
|
400
|
-
message.append_ints @offset, @limit, MatchModes[@match_mode],
|
411
|
+
message.append_ints @offset, @limit, MatchModes[@match_mode],
|
412
|
+
RankModes[@rank_mode], SortModes[@sort_mode]
|
401
413
|
message.append_string @sort_by
|
402
414
|
|
403
415
|
# Query
|
@@ -411,7 +423,8 @@ module Riddle
|
|
411
423
|
message.append_string index
|
412
424
|
|
413
425
|
# ID Range
|
414
|
-
message.
|
426
|
+
message.append_int 1
|
427
|
+
message.append_64bit_ints @id_range.first, @id_range.last
|
415
428
|
|
416
429
|
# Filters
|
417
430
|
message.append_int @filters.length
|
@@ -442,6 +455,16 @@ module Riddle
|
|
442
455
|
message.append_int val
|
443
456
|
end
|
444
457
|
|
458
|
+
# Max Query Time
|
459
|
+
message.append_int @max_query_time
|
460
|
+
|
461
|
+
# Per Field Weights
|
462
|
+
message.append_int @field_weights.length
|
463
|
+
@field_weights.each do |key,val|
|
464
|
+
message.append_string key
|
465
|
+
message.append_int val
|
466
|
+
end
|
467
|
+
|
445
468
|
message.to_s
|
446
469
|
end
|
447
470
|
|
@@ -480,7 +503,7 @@ module Riddle
|
|
480
503
|
|
481
504
|
message.append_int values_by_doc.length
|
482
505
|
values_by_doc.each do |key,values|
|
483
|
-
message.
|
506
|
+
message.append_64bit_int key # document ID
|
484
507
|
message.append_ints *values # array of new values (integers)
|
485
508
|
end
|
486
509
|
|
@@ -5,6 +5,7 @@ module Riddle
|
|
5
5
|
class Message
|
6
6
|
def initialize
|
7
7
|
@message = ""
|
8
|
+
@size_method = @message.respond_to?(:bytesize) ? :bytesize : :length
|
8
9
|
end
|
9
10
|
|
10
11
|
# Append raw data (only use if you know what you're doing)
|
@@ -16,7 +17,7 @@ module Riddle
|
|
16
17
|
|
17
18
|
# Append a string's length, then the string itself
|
18
19
|
def append_string(str)
|
19
|
-
@message << [str.
|
20
|
+
@message << [str.send(@size_method)].pack('N') + str
|
20
21
|
end
|
21
22
|
|
22
23
|
# Append an integer
|
@@ -24,6 +25,10 @@ module Riddle
|
|
24
25
|
@message << [int].pack('N')
|
25
26
|
end
|
26
27
|
|
28
|
+
def append_64bit_int(int)
|
29
|
+
@message << [int >> 32, int & 0xFFFFFFFF].pack('NN')
|
30
|
+
end
|
31
|
+
|
27
32
|
# Append a float
|
28
33
|
def append_float(float)
|
29
34
|
@message << [float].pack('f').unpack('L*').pack("N")
|
@@ -34,6 +39,10 @@ module Riddle
|
|
34
39
|
ints.each { |int| append_int(int) }
|
35
40
|
end
|
36
41
|
|
42
|
+
def append_64bit_ints(*ints)
|
43
|
+
ints.each { |int| append_64bit_int(int) }
|
44
|
+
end
|
45
|
+
|
37
46
|
# Append multiple floats
|
38
47
|
def append_floats(*floats)
|
39
48
|
floats.each { |float| append_float(float) }
|
@@ -28,6 +28,13 @@ module Riddle
|
|
28
28
|
return int
|
29
29
|
end
|
30
30
|
|
31
|
+
def next_64bit_int
|
32
|
+
high, low = @str[@marker, 8].unpack('N*N*')[0..1]
|
33
|
+
@marker += 8
|
34
|
+
|
35
|
+
return (high << 32) + low
|
36
|
+
end
|
37
|
+
|
31
38
|
# Return the next float value from the stream
|
32
39
|
def next_float
|
33
40
|
float = @str[@marker, 4].unpack('N*').pack('L').unpack('f*').first
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ultrasphinx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.8"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ""
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
yZ0=
|
31
31
|
-----END CERTIFICATE-----
|
32
32
|
|
33
|
-
date: 2008-
|
33
|
+
date: 2008-02-05 00:00:00 -05:00
|
34
34
|
default_executable:
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
metadata.gz.sig
CHANGED
Binary file
|