你如何急切地加载限制?

时间:2011-06-25 12:06:35

标签: ruby-on-rails optimization activerecord eager-loading

在热切加载的文档中,声明:


如果您急切加载与指定的:limit选项的关联,它将被忽略,返回所有关联的对象:

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

Picture.find(:first,:include =&gt;:most_recent_comments).most_recent_comments#=&gt;返回所有相关的评论。


如果是这种情况,那么实现加载“限制”的最佳方法是什么?

假设我们急切地将最近10篇博客帖子加载到博客的首页上,我们显然不希望它们都是如此,那么是否应该指定帖子集合的限制和排序?

除此之外,可以在深度加载的元素上指定相同的条件 - 例如,只显示每篇博文上的前三个评论吗?

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

3 个答案:

答案 0 :(得分:5)

我相信这是因为sql中的LIMIT命令无法很好地转换为您尝试执行的操作。 LIMIT将限制查询返回的总行数。你不是试图这样做。您试图限制为返回的每张图片加入的行数。为了实现这种影响,您必须使用一些复杂的SQL,如果您的表很大,可能很难优化。那时我会考虑你为什么要限制急切加载的行。

如果急切加载的最大注释数量是可管理的(&lt; 2000左右),您可能不必担心限制SQL端。

如果您只加载10个帖子,我会考虑不要急于加载。我不希望额外的10个查询减慢速度,并且他们添加的时间,您可以通过尝试其他优化技术(如缓存)来弥补。

您应该让范围为您执行脏工作,而不是关联。这提高了可重用性,可维护性和可读性。例如:

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

那种方式.comments就在您需要的时候就可以了,您也可以将其范围缩小:

@picture.comments.recent

答案 1 :(得分:0)

我已经使用了will_paginate来帮助我进行急切加载(using includes)因为我必须一次性加载许多相关模型而不使用使用limit

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

或(没有will_paginate(使用 limit

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

...试一试..希望它有所帮助。

答案 2 :(得分:-1)

您可以使用此结构: Picture.find(:first, :include => :most_recent_comments).most_recent_comments.limit(10)

AR guide

中查看详情