2011-02-07 68 views
0

在我的Rails應用程序中,我有一個「術語」模型,它存儲術語(關鍵字)以及它在特定文檔集中出現的頻率一個整數)。無論何時將新文檔添加到集合中,我都會解析出單詞,然後我需要將新術語及其頻率插入術語表中,或者我需要更新現有術語的頻率。Rails - 插入新數據,或增加更新的現有值

最簡單的方法是做一個查找,然後如果它是空的做一個插入,或者如果它不是空的,按正確的數量增加現有記錄的頻率。然而,每個單詞有兩個查詢,並且具有高字數的文檔將導致查詢的長度很長。有沒有更有效的方法來做到這一點?

+0

您正在回答你自己的問題。無論你做什麼,你總是需要一個查找和創建/更新每個單詞。 – nunopolonia 2011-02-07 01:30:13

回答

1

實際上,您可以非常有效地做到這一點。那麼,如果你不害怕調整Rails的默認表格佈局一點,如果你不害怕生成自己的原始SQL ...

我會假設你正在使用MySQL數據庫(我不確定其他數據庫支持這個):你可以使用INSERT ... ON DUPLICATE KEY UPDATE來做到這一點。

你必須調整你的計數表才能使它工作,但「重複鍵」只是指主鍵,而Rails的默認ID,它只是一個任意數字,不會幫助你。您需要更改主鍵,以便確定每條記錄的獨特性 - 在您的情況下,我會說PRIMARY KEY(word, document_set_id)。默認情況下,Rails可能不支持這種方式,但至少有一個plugin,如果您不喜歡那個,可能還會多一個。

一旦你的數據庫設置好了,你可以構建一個巨大的插入語句,然後在MySQL中拋出它,讓查詢的「重複鍵」部分照顧到惡意的存在 - 檢查你的東西(注意:有插件做批量插入,太多,但我不;知道他們是如何工作 - 特別是在「關於重複鍵」問候):

counts = {} 
#This is just demo code! Untested, and it'll leave in punctuation... 
@document.text.split(' ').each do |word| 
    counts[word] ||= 0 
    counts[word] += 1 
end 

values = [] 
counts.each_pair do |word, count| 
    values << ActiveRecord::Base.send(:sanitize_sql_array, [ 
     '(?, ?, ?)', 
     word, 
     @document.set_id, 
     count 
    ]) 
end 

#Massive line - sorry... 
ActiveRecord::Base.connection.execute("INSERT INTO word_counts (word, document_set_id, occurences) VALUES ${values.join(', ')} ON DUPLICATE KEY UPDATE occurences = occurences + VALUES(occurences)") 

這會做到這一點 - 在一個SQL查詢整個新文件。應該快得多,一半是因爲你只運行一個查詢,另一半是因爲你已經避開了ActiveRecord的緩慢查詢構建。

希望有幫助!