2013-08-30 101 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子句中使用的所有表。