2013-10-11 1 views
2

J'utilise pg_search gem à mon application pour la fonction de recherche. Avant d'ajouter pg_search, j'ai déjà ajouté 130 000 lignes de données à une table dans ma base de données Postgres. Maintenant, quand je lance une recherche, cela prend trop de temps, c'est-à-dire 16 000 ms.Rechercher trop lent. Comment puis-je réindexer la base de données postgres dans une application rails en utilisant pg_search gem?

Je suivais Railscasts Episode343 recherche de texte intégral dans PostgreSQL

Voici le code dans mon modèle pour pg_search:

include PgSearch 
pg_search_scope :search, :against => [:applicant, :generic_name, :trade_name, :description], 
using: {tsearch: {dictionary: "english"}}, 
ignoring: :accents 

def self.text_search(query) 
    if query.present? 
     rank = <<-RANK 
      ts_rank(to_tsvector(generic_name), plainto_tsquery(#{sanitize(query)})) + 
      ts_rank(to_tsvector(trade_name), plainto_tsquery(#{sanitize(query)}))+ 
      ts_rank(to_tsvector(description), plainto_tsquery(#{sanitize(query)})) + 
      ts_rank(to_tsvector(applicant), plainto_tsquery(#{sanitize(query)})) 
     RANK 
     where("generic_name @@ :q or trade_name @@ :q or description @@ :q or applicant @@ :q", q: query) 
    else 
     all 
    end 
end 

Et ma sortie du serveur est la suivante:

Parameters: {"utf8"=>"✓", "query"=>"intraocular lenses"} 
    Parameters: {"utf8"=>"✓", "query"=>"intraocular lenses"} 
    Rendered layouts/_search.html.erb (1.5ms) 
    Rendered layouts/_search.html.erb (1.5ms) 
    Rendered medicaldevices/index.html.erb within layouts/application (16535.9ms) 
    Rendered medicaldevices/index.html.erb within layouts/application (16535.9ms) 
    Rendered layouts/_header.html.erb (1.8ms) 
    Rendered layouts/_header.html.erb (1.8ms) 
    Rendered layouts/_footer.html.erb (0.1ms) 
    Rendered layouts/_footer.html.erb (0.1ms) 
Completed 200 OK in 16574ms (Views: 60.3ms | ActiveRecord: 16510.7ms) 
Completed 200 OK in 16574ms (Views: 60.3ms | ActiveRecord: 16510.7ms) 

Voici mon fichier de migration pour l'indexation

class AddSearchIndexToMedicaldevices < ActiveRecord::Migration 

def up 
    execute "create index generic_name on medicaldevices using gin(to_tsvector('english',  generic_name))" 
    execute "create index trade_name on medicaldevices using gin(to_tsvector('english', trade_name))" 
    execute "create index description on medicaldevices using gin(to_tsvector('english', description))" 
    execute "create index applicant on medicaldevices using gin(to_tsvector('english', applicant))" 
    end 

    def down 
    execute "drop index generic_name" 
    execute "drop index trade_name" 
    execute "drop index description" 
    execute "drop index applicant" 
    end 

end 
+0

Lire les documents de recherche de texte PostgreSQL donnerait que vous devriez utiliser un index GIN. –

Répondre

3

Voici votre réponse, je pense (http://www.postgresql.org/docs/8.3/static/textsearch-tables.html)

12.2.2. Création d'index

Nous pouvons créer un index GIN (section 12.9) pour accélérer les recherches de texte:

CREATE INDEX pgweb_idx ON pgweb USING gin(to_tsvector('english', body)); 

Notez que la version 2 argument de to_tsvector est utilisé. Seules les fonctions de recherche de texte qui spécifient un nom de configuration peuvent être utilisées dans les index d'expression (Section 11.7). C'est parce que le contenu de l'index ne doit pas être affecté par default_text_search_config. Si elles étaient affectées, le contenu de l'index pourrait être incohérent car des entrées différentes pourraient contenir des tsvectors créés avec différentes configurations de recherche de texte, et il n'y aurait aucun moyen de deviner lequel était quoi. Il serait impossible de vider et restaurer correctement un tel index. Étant donné que la version à deux arguments de to_tsvector a été utilisée dans l'index ci-dessus, seule une référence de requête qui utilise la version à 2 arguments de to_tsvector avec le même nom de configuration utilisera cet index. C'est à dire, où to_tsvector ('anglais', corps) @@ 'un & b' peut utiliser l'index, mais où to_tsvector (corps) @@ 'un & b' ne peut pas. Cela garantit qu'un index ne sera utilisé qu'avec la même configuration que celle utilisée pour créer les entrées d'index.

1

Sergio, J'ai suivi le chemin que vous avez mentionné et cela a fonctionné. je devais changer mon ancien code ci-dessus pour ce qui suit:

where("to_tsvector('english', generic_name) @@ plainto_tsquery(:q) or 
     to_tsvector('english', trade_name) @@ plainto_tsquery(:q) or 
     to_tsvector('english', description) @@ plainto_tsquery(:q) or 
     to_tsvector('english', applicant)@@ plainto_tsquery(:q)", q: query).order("#{rank} DESC") 

je devais ajouter planto_tsquery (q) pour rechercher une recherche de plusieurs mots. Merci!

Questions connexes