这与一年前的一个问题有关.
我提出了一个开箱即用的问题示例,只要你有sqlite3可用:https://github.com/cairo140/rails-eager-loading-counts-demo
git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s
我在存储库中有更全面的文章,但我的一般问题是这个.
如何以最小化数据库查询的方式使Rails急切加载计数?
尽管在ActiveRelation 中包含了该关联,但n+1只要您#count在关联上使用该问题就会出现问题#includes(:associated).一种解决方法是使用#length,但只有当它被调用的对象已被加载时才能正常工作,更不用说我怀疑它复制了Rails内部已经完成的东西.此外,使用的一个问题#length是,当开始时没有加载关联时,它会导致不幸的过载,并且只需要计数.
从自述文件:
我们可以通过在posts数组上运行#length来解决这个问题(参见附录),这已经加载了,但是也可以随时使用.它不仅更加一致; 它提供了一个访问路径,不一定需要加载帖子.例如,如果你有一个部分显示计数,无论什么,但一半的时间,部分是在加载帖子和一半时间没有调用,你面临以下情况:
- 运用
#count
- n
COUNT已经加载帖子时的样式查询- n
COUNT尚未加载帖子时的样式查询- 运用
#length
- 在已加载帖子时将其他查询归零
- n
*尚未加载帖子时的样式查询在这两种选择之间,没有主导选择.但是修改#count来推迟#length或访问存储在幕后的其他方式的长度会很好,这样我们就可以得到以下场景:
- 使用修改
#count
- 在已加载帖子时将其他查询归零
- n
COUNT尚未加载帖子时的样式查询
那么这里的正确方法是什么?有没有我忽略的东西(非常非常可能)?
我查看了Arel源代码,以及Rails 3.0的一些activerecord源代码,但我似乎无法为自己收集一个很好的答案,因为在构造查询时Arel是否会改变我们使用includes()的能力, 为了更好.
有些情况下,人们可能想要修改activerecord上的条件:包括2.3.5及之前的查询,用于返回的关联记录.但据我所知,这对于所有人来说都不是以编程方式成立的:包含查询:
(我知道一些AR-find-includes make t#{n} .c#{m}重命名所有属性,可以想象为这些查询添加条件以限制连接集的结果;但是其他人做n_joins + 1个数字迭代地对id设置的查询,我不确定如何破解AR来编辑这些迭代查询.)
Will Arel允许我们构造ActiveRecord查询,在使用includes()时指定结果关联的模型对象?
例如:
User :has_many posts( has_many :comments)
User.all(:include => :posts) #say I wanted the post objects to have their 
 #comment counts loaded without adding a comment_count column to `posts`.
#At the post level, one could do so by: 
posts_with_counts = Post.all(:select => 'posts.*, count(comments.id) as comment_count', 
         :joins => 'left outer join comments on comments.post_id = posts.id',
         :group_by => 'posts.id') #i believe
#But it seems impossible to do so while …