Exclude Records With UltraSphinx
August 20th, 2008
So been using Sphinx with the UltraSphinx plugin and I came across the requirement to use filters to reject records. Unfortunately in the plugin the filters are hardwired to submit the ‘exclude’ parameter as ‘false’ i.e include. Time for a quick hack I think…....
Very easy to fix, just open up the ‘internals.rb’ file in the UltraSphinx plugin or include the gem using ‘rake gems:unpack GEM=ultrasphinx’ (need to have config.gem “ultrasphinx” set in envrinoment.rb) and then find that file.
Ok, so found the file? On line 97 is this loop:
Array(opts['filters']).each do |field, value|
....
begin
case value
when Integer, Float, BigDecimal, NilClass, Array
# XXX Hack to force floats to be floats
value = value.to_f if type == 'float'
# Just bomb the filter in there
request.filters << Riddle::Client::Filter.new(field, Array(value), false)
when Range
....
end
The ‘Riddle::Client::Filter.new(field, Array(value), false)’ call is the one we need to change (the ‘false’ is the exclude param).
So what I did was to change that loop to:
Array(opts['filters']).each do |field, value|
field = field.to_s
type = Fields.instance.types[field]
# Special derived attribute
if field == 'distance' and options['location']
field, type = '@geodist', 'float'
end
raise UsageError, "field #{field.inspect} is invalid" unless type
# ADDED FROM HERE
exclude = false
# check for exclude flag
if value.is_a? Hash
exclude = value[:exclude]
value = value[:value]
end
# TO HERE
begin
case value
when Integer, Float, BigDecimal, NilClass, Array
# XXX Hack to force floats to be floats
value = value.to_f if type == 'float'
# Just bomb the filter in there
# CHANGE CALL HERE TO PASS THE exclude PARAMETER
request.filters << Riddle::Client::Filter.new(field, Array(value), exclude)
when Range
# Make sure ranges point in the right direction
min, max = [value.begin, value.end].map {|x| x._to_numeric }
raise NoMethodError unless min <=> max and max <=> min
min, max = max, min if min > max
# XXX Hack to force floats to be floats
min, max = min.to_f, max.to_f if type == 'float'
# CHANGE CALL HERE TO PASS THE exclude PARAMETER
request.filters << Riddle::Client::Filter.new(field, min..max, exclude)
when String
# XXX Hack to move text filters into the query
opts['parsed_query'] << " @#{field} #{value}"
else
raise NoMethodError
end
rescue NoMethodError => e
raise UsageError, "Filter value #{value.inspect} for field #{field.inspect} is invalid"
end
end
Now I can do searches like
@search = Ultrasphinx::Search.new(
:query => params[:q],
:page => page,
:class_names => ["User"],
:filters => {:id => {:value => current_user.id, :exclude => true}}
)
And the current_user gets excluded, cool.
August 21st, 2008 at 02:39 AM Can you submit a GitHub patch for this?
August 21st, 2008 at 05:11 PM Hi Evan, yep sure. I'll get on it.
November 24th, 2008 at 04:27 PM I confirm. You can submit a GitHub patch.
March 3rd, 2009 at 02:35 PM Hello webmaster I would like to share with you a link to your site write me here preonrelt@mail.ru