2013-11-24 13 views
5

ho requisito come di seguitomodo migliore per ottimizzare interrogazione durante la ricerca della stringa in grandi frasi

poesia appartiene al poeta

poeta ha molte poesie

Se l'utente alla ricerca di parola "ruby "

Dovrebbe dare,

Numero totale di volte in cui la parola rubino è usata in tutte le poesie.

Mostra tutte le poesie che hanno la parola rubino.

Numero di volte in cui la parola rubino è usata in ogni poesia.

Il numero totale di poeti utilizzava la parola rubino.

Numero totale di volte in cui ogni poeta utilizzava la parola ruby.

Quindi la mia domanda nel modello di Poema è qui

poems= where("poem_column like ?", "%#{word}%") 
    @results = {} 
    poems.each do |poem| 
     words = poem.poem_column.split 
     count = 0 
     words.each do |word| 
     count += 1 if word.upcase.include?(word.upcase) 
     end 
     @results[poem] = count # to get each poem using word ruby 
    end 

E per ottenere contare poeti nel Poema modello

@poets = poems.select("distinct(poet_id)") 
     @poets.each do |poet| 
     @poets_word_count << poems.where("poet_id = #{poem.poet_id}").count 
     end 

Dove poesie sono circa 50k. sta prendendo quasi più di 1 minuto. So che sto facendo nel modo sbagliato ma non sono riuscito a ottimizzarlo in nessun altro modo.

penso che le righe sottostanti impiegano troppo tempo mentre avvolgono ogni parola di tutte le poesie.

 words.each do |word| 
     count += 1 if word.upcase.include?(word.upcase) 
     end 

Può qualcuno di voi mi mostra il modo per ottimizzare it.As mancanza di conoscenza nelle query non potevo farlo in qualsiasi altro modo.

Grazie in anticipo

+0

sai dove ti prendi più tempo: ottenere i poeti? ottenere il numero di occorrenze per la parola cercata all'interno di poem_column? – juanpastas

+0

Entrambi richiedono tempo ma ricercano la parola all'interno di poem_column prendendo di più. [Colonna poesia contiene fino a 20 righe] – devudilip

+0

Considera l'utilizzo di [Ricerca testo completo SQLite3] (http://www.sqlite.org/fts3.html). –

risposta

1

Non una risposta, solo un test.

In primo luogo, ridurre i dati estrazione parole chiave per ogni poesia come essi vengono salvati:

rails g resource Keyword word occurrences poem_id:integer 
rails db:migrate 

Poi nel modello Poema:

# add more words 
EXCLUDED_WORDS = %w(the a an so that this these those) 

has_many :keywords 

before_save :set_keywords 

# { :some => 3, :word => 2, :another => 1} 
def keywords_hash(how_many = 5) 
    words = Hash.new 0 
    poem_column.split.each do |word| 
    words[word] += 1 if not word.in? EXCLUDED_WORDS 
    end 
    Hash[words.sort { |w, w1| w1 <=> w }.take(how_many)] 
end 

def set_keywords 
    keywords_hash.each do | word, occurrences | 
    keywords.create :word => word, :occurrences => occurrences 
    end 
end 

In Keyword modello:

belongs_to :poem 

def self.poem_ids 
    includes(:poem).map(&:poem_id) 
end 

def self.poems 
    Poem.where(id: poem_ids) 
end 

Quindi, quando hai una parola da cercare:

keywords = Keyword.where(word: word) 
poems = keywords.poems 
poets = poems.poets 

Per utilizzare questa ultima parte, si avrebbe bisogno in Poem modello:

def self.poet_ids 
    includes(:poet).map(&:poet_id) 
end 

def self.poets 
    Poet.where(id: poet_ids) 
end 

Per quanto riguarda la vedo in questo modo richiederebbe solo 3 domande, non si unisce, così sembra avere senso.

Penso a come estendere questo modo per cercare l'intero contenuto.

+0

l'unica cosa è il problema del database, dato che dobbiamo memorizzare le informazioni di ogni parola o il suo tempo veramente ridotto.grazie e applausi Ancora una volta la tabella delle parole chiave avrà milioni di dati – devudilip

+0

SQLite pieno la ricerca testuale ha molto più senso, nel commento @LS_dev. Stavo per suggerire di passare a un DB di produzione più usuale e utilizzare la ricerca full-text, come PostgreSQL e usare la gemma 'pg_search'. – juanpastas

0

Im mio opnion, è possibile modificare seguente codice citato dal tuo post:

poems.each do |poem| 
    words = poem.poem_column.split 
    count = 0 
    words.each do |word| 
    count += 1 if word.upcase.include?(word.upcase) 
    end 
    @results[poem] = count # to get each poem using word ruby 
end 

a:

poems.each {|poem| @results[poem] = poem.poem_column.scan(/ruby/i).size} 
+0

non fa alcuna differenza :-( – devudilip