How do you do eager loading with limits?

送分小仙女□ 提交于 2019-12-03 11:55:43

问题


In the documentation for eager loading it is stated that:


If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects:

class Picture < ActiveRecord::Base
  has_many :most_recent_comments, :class_name => 'Comment', 
                                  :order => 'id DESC', :limit => 10
end

Picture.find(:first, :include => :most_recent_comments).most_recent_comments # => returns all associated comments.


If this is the case then what is the best way to achieve the "limit" on the loading?

Let's say we're eager loading the last 10 blog posts onto the front page of a blog, we clearly don't want them all so should the limit and ordering of the post collection be specified?

Further to that, can one specify the same conditions on elements that are deep loaded - for instance only show the first three comments on each blog post?

Blog.find(:blog_id, :include => {:posts => :comments } )

回答1:


I believe this is because the LIMIT command in sql doesn't translate well to what you are trying to do. LIMIT will limit the total rows returned by the query. You aren't trying to do that though. You are trying to limit the number of rows joined for each picture returned. In order to achieve this affect you'd have to use some complex SQL, which might be hard to optimize if your tables are large. At that point I would consider why you are trying to limit the rows eager loaded.

If the max number of comments eager loaded is manageable (< 2000 or so), you should probably not worry about limiting on the SQL end.

If you're only loading 10 posts though, I would consider not eager loading at all. I wouldn't expect an extra 10 queries to slow things down much, and what time they did add, you could make up for by trying other optimization techniques such as caching.

You should let scopes do the dirty work for you, not the assocation. This promotes reusability, maintainability, readability. Example:

Class Picture < ActiveRecord::Base
  has_many :comments, :order => 'id DESC' do
    def recent
      limit(10)
    end
  end
end

That way .comments is there when you need it, and you can also scope it down like this:

@picture.comments.recent



回答2:


i have used will_paginate to help me out along with eager loading(using includes) as i have to load many associated models in one shot without using limit

Image.includes(:user,:tags).where("user_id !=?",current_user.id).paginate(:page => params[:page], :per_page => 15)

OR(without will_paginate (using limit)

Image.includes(:user,:tags).where("user_id !=?",current_user.id).limit(30).order("created_at ASC")

...give it a try..hope it helps.




回答3:


You can use this construction: Picture.find(:first, :include => :most_recent_comments).most_recent_comments.limit(10)

See more in AR guide



来源:https://stackoverflow.com/questions/6477614/how-do-you-do-eager-loading-with-limits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!