Для тех, кто может столкнуться с подобной проблемой. Я, наконец, получил эту работу, используя эту статью http://www.scottlowe.eu/blog/2011/04/28/postgresql-full-text-search-is-often-good-enough/
Как объяснил все, что вам нужно, это добавить tsearch
столбец в таблице (В этой таблице тематические статьи)
class AddTsearchToArticle < ActiveRecord::Migration
def self.up
execute(<<-'eosql'.strip)
ALTER TABLE articles ADD COLUMN tsv tsvector;
CREATE FUNCTION articles_generate_tsvector() RETURNS trigger AS $$
begin
new.tsv :=
setweight(to_tsvector('pg_catalog.english', coalesce(new.title,'')), 'A') ||
setweight(to_tsvector('pg_catalog.english', coalesce(new.body,'')), 'B');
return new;
end
$$ LANGUAGE plpgsql;
CREATE TRIGGER tsvector_articles_upsert_trigger BEFORE INSERT OR UPDATE
ON articles
FOR EACH ROW EXECUTE PROCEDURE articles_generate_tsvector();
UPDATE articles SET tsv =
setweight(to_tsvector('pg_catalog.english', coalesce(title,'')), 'A') ||
setweight(to_tsvector('pg_catalog.english', coalesce(body,'')), 'B');
CREATE INDEX articles_tsv_idx ON articles USING gin(tsv);
eosql
end
def self.down
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS articles_tsv_idx;
DROP TRIGGER IF EXISTS tsvector_articles_upsert_trigger ON articles;
DROP FUNCTION IF EXISTS articles_generate_tsvector();
ALTER TABLE articles DROP COLUMN tsv;
eosql
end
end
В модели вы могли бы просто
class Article < ActiveRecord::Base
validates :title, :body, :presence => true
# Note that ActiveRecord ARel from() doesn't appear to accommodate "?"
# param placeholder, hence the need for manual parameter sanitization
def self.tsearch_query(search_terms, limit = query_limit)
words = sanitize(search_terms.scan(/\w+/) * "|")
Article.from("articles, to_tsquery('pg_catalog.english', #{words}) as q").
where("tsv @@ q").order("ts_rank_cd(tsv, q) DESC").limit(limit)
end
# Selects search results with plain text title & body columns.
# Select columns are explicitly listed to avoid returning the long redundant tsv strings
def self.plain_tsearch(search_terms, limit = query_limit)
select([:title, :body, :id]).tsearch_query(search_terms, limit)
end
def self.query_limit; 25; end
end
Затем в контроллере
@articles = Article.plain_tsearch(params[:search])
Это сделало это для меня! Надеюсь, поможет.
См. [Как выполнять полнотекстовый поиск на основе фразы в postgres, который использует полнотекстовый индекс?] (Http://stackoverflow.com/q/1489617/238814) –