Manual Thinking Sphinx Attributes
Anton, 23 May 07:58
Let's continue to talk about using Thinking Sphinx with Postgresql.
Imagine, I have a Hotel table with a price column, which I want to index and in the future to do a search by price.
Let's define migration:
create_table :hotels do |t| t.string :name t.decimal :price, :precision => 8, :scale => 2 t.string :currency, :default => "USD" endAnd define model:
class Hotel < ActiveRecord::Base
define_index do
indexes name
has price
end
end But the problem is that price can be specified in different currencies. And I want to make searches in only one currency. So we need to add a table with the daily changes in exchange rates.
create_table :currency_rates do |t| t.date :rate_date t.decimal :usd, :precision => 8, :scale => 4, :default => 1 t.decimal :eur, :precision => 8, :scale => 4 t.decimal :rur, :precision => 8, :scale => 4 ... all other needed currencies t.timestamps endIn addition, we have to convert each price to the desired currency when sphinx will build index. Let's define price_to_usd function:
CREATE OR REPLACE FUNCTION price_to_usd(price float, currency varchar) RETURNS integer AS $$ DECLARE rate float; BEGIN EXECUTE 'SELECT "' || lower(currency) || '" FROM currency_rates ORDER BY rate_date desc, created_at desc LIMIT 1' INTO rate; RETURN CAST(price*rate AS int); END; $$ LANGUAGE plpgsql;Then we need to modify sphinx index:
class Hotel < ActiveRecord::Base
define_index do
indexes name
has "price_to_usd(hotels.price, hotels.currency)", :as => :price_usd, :type => :integer
group_by "price_to_usd(hotels.price, hotels.currency)"
end
end Important point is that we need to manually add group by expression for such manual attributes. This is all. So let's try to search: $ rake ts:reindex
$ rails c
>> Hotel.search("", {:with => {:price_usd => 100..300}}).total_entries
=> 1194
Read more...