2017-08-11 25 views
0

我有一個模型,在本例中我們稱其爲Product模型。我在這個數據庫中有大約200k條記錄,其中一半是activeactive: true),一半不是。當用戶正在搜索產品時,我只希望顯示活動的產品。我的代碼看起來是這樣的:Rails:如何在不將內容加載到內存中的情況下過濾搜索結果

def self.search 
    products = Products.where(active: true).order("`foo` = 'BAR'") 
    products = products.where(other_filters) 
    products = products.where(more_filters) 
    .. 
end 

這樣做加載第一個10萬點活躍的到內存(做第一where回報100000puts products.size),然後這些帶有鏈接where條款和過濾下降了約20次以上最後分頁顯示,只顯示25。有沒有更有效的方法來過濾這些結果?

+0

您是否使用了一些ORM,比如ActiveRecord?您可以鏈接.where來確保數據庫只返回匹配所有過濾器的數據庫。 –

+0

在ActiveRecord鏈接'.where'創建一個單一的查詢。您還可以使用['.merge'](http://api.rubyonrails.org/classes/ActiveRecord/SpawnMethods.html#method-i-merge)將範圍合併在一起。你真的只是在尋找一種不太笨重的方法來解決它嗎? – max

回答

3

where不運行數據庫查詢,而是返回ActiveRecord::Relation的實例。事實上,你的例子根本不運行數據庫查詢。它只會把更多的條件聯繫起來。

當您實際需要記錄返回結果時,會運行對數據庫的實際查詢。觸發從數據庫加載的方法的一些示例:count,first,each,map, loadinspect

這就是說,只要你不輸出中間結果(例如puts),你是安全的,你不需要運行必要的查詢。只需將所有條件鏈接起來。

順便說一句,你可能希望通過刪除products變量來簡化代碼:

def self.search 
    Products 
    .where(active: true) 
    .order("`foo` = 'BAR'") 
    .where(other_filters) 
    .where(more_filters) 
    # ... 
end 
+0

就像一個快速的一面注意:'to_s'不運行查詢,但'inspect'。 'puts'的確如此,因爲(我認爲)它是類似數組的,所以每個元素都被輸出到一個新行(從而運行'each'或等價物) –

相關問題