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 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 2007 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.
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 at http://rubyforge.org/frs/download.php/25331/evan_weaver-original-public_cert.pem.
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 r871
16
- * Rails 1.2.3
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 development snapshot (http://www.sphinxsearch.com), 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.
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>example/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.
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
- * http://rubyforge.org/forum/forum.php?forum_id=14244
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
@@ -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).class_name.constantize
18
- end
19
-
20
- def entry_identifies_association?(entry)
21
- entry['class_name'] || entry['association_name']
22
- end
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['table']}.#{entry['field']}"
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['table']} ON " +
210
+ "LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['table_alias']} ON " +
211
211
  if (macro = association.macro) == :belongs_to
212
- "#{entry['table']}.#{join_klass.primary_key} = #{klass.table_name}.#{association.primary_key_name}"
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['table']}.#{association.primary_key_name}"
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['table']}.#{entry['field']}"
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 entry_identifies_association?(entry) and entry['field']
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['table']} ON #{klass.table_name}.#{klass.primary_key} = #{entry['table']}.#{association.primary_key_name}" +
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['table']}.#{entry['field']}"
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['table']}.#{subfield}"
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 << "CRC32(#{source_string}) AS #{as}_facet"
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
@@ -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' => 'integer'
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 'float', 'integer'
53
- "sql_group_column = #{field}"
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
- "sql_date_column = #{field}"
59
+ "sql_attr_timestamp = #{field}"
56
60
  when 'text'
57
- "sql_str2ordinal_column = #{field}" if string_sortable
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['table']
156
- # Getting run twice; don't know why
157
- if entry['field'] and entry['field'].include? "."
158
- # This field is referenced by a table alias
159
- entry['table'], entry['field'] = entry['field'].split(".")
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
- klass = get_association_model(klass, entry) if entry_identifies_association?(entry)
162
- entry['table'] = klass.table_name
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>:filter</tt> element on any date or numeric field, so any <tt>*_id</tt> fields you have will be filterable.
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
- :filter => {'company_id' => 493})
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 int AS $$
6
- SELECT hex_to_int(SUBSTRING(MD5($1) FROM 1 FOR 8))::int
7
- $$ VOLATILE LANGUAGE SQL;
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;
@@ -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
- # override the individual model accessors with the excerpted data
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
- unless Fields.instance.types[field]
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
- ["included.#{configuration['field']}",
191
- (configuration['association_sql'] or "LEFT OUTER JOIN #{configuration['table']} AS included ON included.#{association_model.primary_key} = #{klass.table_name}.#{association_model.class_name.underscore}_id")
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, CRC32(#{field_string}) AS hash FROM #{klass.table_name} #{join_string} GROUP BY value").each do |value, hash|
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)]
@@ -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 :seller
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 => [{:class_name => 'Seller', :field => 'company_name', :as => 'company'},
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
- config.action_controller.session = { :session_key => "_myapp_session", :secret => "7c74979e7db2230f84adbb4b3eb77d05" }
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
- # You can use individual namespaces if you want (e.g. "development.base").
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 = 3313
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
- dictionary_name = ts
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 = 3313
50
+ server_port = 3312
35
51
  }
36
52
 
37
53
  source
38
54
  {
39
55
  # Individual SQL source options
40
- sql_range_step = 20000
41
- strip_html = 0
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 Sat Jan 12 08:05:26 -0500 2008.
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 = 3313
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
- strip_html = 0
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
- sql_group_column = capitalization
40
- sql_group_column = class_id
41
- sql_group_column = company_name_facet
42
- sql_date_column = created_at
43
- sql_group_column = deleted
44
- sql_str2ordinal_column = mission_statement
45
- sql_group_column = user_id
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
- strip_html = 0
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
- sql_group_column = capitalization
71
- sql_group_column = class_id
72
- sql_group_column = company_name_facet
73
- sql_date_column = created_at
74
- sql_group_column = deleted
75
- sql_str2ordinal_column = mission_statement
76
- sql_group_column = user_id
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
- strip_html = 0
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, states.name AS state, 0 AS user_id FROM addresses LEFT OUTER JOIN states AS states ON states.id = addresses.state_id WHERE addresses.id >= $start AND addresses.id <= $end GROUP BY addresses.id
100
-
101
- sql_group_column = capitalization
102
- sql_group_column = class_id
103
- sql_group_column = company_name_facet
104
- sql_date_column = created_at
105
- sql_group_column = deleted
106
- sql_str2ordinal_column = mission_statement
107
- sql_group_column = user_id
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
- strip_html = 0
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, sellers.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 sellers ON users.id = sellers.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
131
-
132
- sql_group_column = capitalization
133
- sql_group_column = class_id
134
- sql_group_column = company_name_facet
135
- sql_date_column = created_at
136
- sql_group_column = deleted
137
- sql_str2ordinal_column = mission_statement
138
- sql_group_column = user_id
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
- strip_html = 0
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
- sql_group_column = capitalization
164
- sql_group_column = class_id
165
- sql_group_column = company_name_facet
166
- sql_date_column = created_at
167
- sql_group_column = deleted
168
- sql_str2ordinal_column = mission_statement
169
- sql_group_column = user_id
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 21, @s.facets['company_name'].size
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
@@ -13,7 +13,7 @@ class ServerTest < Test::Unit::TestCase
13
13
  @pid = Process.fork do
14
14
  Dir.chdir RAILS_ROOT do
15
15
  # print "S"
16
- exec("script/server -p #{PORT} &> /dev/null")
16
+ exec("script/server -p #{PORT} &> #{LOG}")
17
17
  end
18
18
  end
19
19
  sleep(5)
data/test/test_helper.rb CHANGED
@@ -1,11 +1,18 @@
1
1
 
2
2
  require 'rubygems'
3
3
  require 'test/unit'
4
- require 'ruby-debug'
4
+ require 'echoe'
5
5
  require 'multi_rails_init'
6
6
 
7
- HERE = File.dirname(__FILE__)
8
- $LOAD_PATH << HERE
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.7
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"
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-01-12}
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-r985 riddle
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.8r985 are supported.
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
 
@@ -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
- var pageTracker = _gat._getTracker("%analytics%");
75
- pageTracker._initData();
76
- pageTracker._trackPageview();
72
+ _uacct = "%analytics%";
73
+ urchinTracker();
77
74
  </script>
78
75
 
79
76
  </body>
@@ -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 = 985
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 => 0x10F, # VER_COMMAND_SEARCH
35
+ :search => 0x112, # VER_COMMAND_SEARCH
36
36
  :excerpt => 0x100, # VER_COMMAND_EXCERPT
37
- :update => 0x100 # VER_COMMAND_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 ? (response.next_int() << 32) + response.next_int : response.next_int
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], SortModes[@sort_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.append_ints 0, @id_range.first, @id_range.last
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.append_int key # document ID
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.length].pack('N') + 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.7"
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-01-12 00:00:00 -05:00
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