2014-01-03 4 views
0

Хорошо, я реализовал функцию поиска в своем приложении 4 rails, где пользователи могут искать других пользователей по имени. Поиск использует jquery foxycomplete. Поиски, содержащие одно слово, возвращаются успешно. Howerver, когда я делаю поиск фразы (например, джон Хэтфилд) PostgreSQL броски и ошибкифраза поиск в postgresql - Rails 4

syntax error in tsquery: "john hatfield:*" 

Это то, что я имею в моей модели

def self.search(query) 
     conditions = <<-EOS 
         to_tsvector('english', name) @@ to_tsquery('english', ?) 
        EOS 
     where(conditions, query + ':*') 
    end 

Мой контроллер

@users = User.search(params[:q]) 

I «Я искал вокруг Google, и я не могу найти решение моей проблемы. Какие-нибудь идеи? Я хочу быть в состоянии искать. Спасибо

+0

См. [Как выполнять полнотекстовый поиск на основе фразы в postgres, который использует полнотекстовый индекс?] (Http://stackoverflow.com/q/1489617/238814) –

ответ

0

Для тех, кто может столкнуться с подобной проблемой. Я, наконец, получил эту работу, используя эту статью 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]) 

Это сделало это для меня! Надеюсь, поможет.

Смежные вопросы