2013-08-30 39 views
0

我工作的一個功能來搜索項目。預先加載僅結果的第一頁與活動記錄

我的模型是這樣的,roughtly:

User has many items 
User has many addresses 
User has one profile 
Item has many images 
Item has many addresses 
Item belongs to category 

我想顯示用戶分組的結果,例如:

Results for 'Laptop': 

Items of Bob: 
    Laptop dell (details...) 
    Samsung laptop (details...) 

Items of Alice: 
    Laptop HP (details...) 
... 

所以我有一個預先加載這個大查詢:

r = User.includes([{items: [:images, :addresses, :category]}, :addresses, :profile]). 
    joins(:items). 
    where('query like "%laptop%"'). 
    where(...). 
    limit(80). 
    all 
# then get the first page of results with kaminary 

然後我用erb中的這樣一個循環顯示:

r.each do |u| 
    # items of user u 
    u.items do |i| 
    # item i 
    end 
end 

一切工作正常,除了預先加載需要時間looong。通過急於加載只有顯示的第一頁上的項目可能會快得多。

這是可能的活動記錄,以急於負載只記錄了條件?例如:User.includes([:table1, table2], conditions: 'users.id in (1,2,3)')

另一種解決辦法是執行與極限20大請求,然後重做不預先加載了極限80的請求,然後手動合併的結果,但這是複雜的?

任何其他建議?

回答

0

我結束了做兩個請求,結果都融合在一起。這並不難,因爲它的聲音:

# per_page is 20 
limit = "#{(page.to_i - 1) * 20}, #{(page.to_i * 20)}" 
query = Users.where('items.title LIKE "%whatever%"').where('addresses.lat < 50') 
return query.includes([{items: [:images, :category]}, :profile, :addresses]). 
    joins(:items).   
    limit(limit).all | 
    query.select('DISTINCT users.*').joins(:items, :addresses). 
    limit(200).all 

備註1:

這渴望只將當前頁面的20個元素,並增加了對不預先加載其他頁面的所有元素。例如,假設您在第3頁上,第一個請求會急於加載limit 60, 80,並添加元素#0到#199。數組聯合(運算符|)在ruby中的工作方式是,如果兩個數組中都存在相同的元素,則會保留第一個數組中的元素。在這種情況下,第一個數組中的元素將加載該元素。因此,如果我們有三個頁面,它會最終陣列中的合併[60..80] (eager loaded)[1..200] (not eager loaded)和元素60至80將是第一個數組中的人。

備註2:

的選擇不同是重要的,因爲沒有它的限制將在項目或地址的數目進行限制。例如,如果用戶#1具有198個對象,則第二個查詢將返回如下內容:

user 1 - item 1 of user 1 
    user 1 - item 2 of user 1 
    ... 
    user 1 - item 198 of user 1 
    user 2 - item 1 of user 2 
    user 3 - item 1 of user 3 

而且這不會正確預加載。合併後,我們會有用戶[1,2,3,60,61,... 80]。

隨着不同,結果將是:

user 1 - item 1 of user 1 
    user 2 - item 1 of user 2 
    user 3 - item 1 of user 3 
    ... 
    user 200 - item 1 of user 200 

我們將具有[1,2,3 ... 200]合併,用元件60〜80從第一個查詢服用後。

注3:

在第二個查詢,我們要參加在where子句中使用的所有表。