如何使用DataMapper聚合避免N + 1

时间:2011-02-03 17:30:49

标签: ruby datamapper

如果我有一个Foo类型的模型,它有许多Bar类型的子记录,我希望能够显示一个Foo记录列表并显示子Bar记录的数量。所以我有类似......

@foos.each do |foo|
  puts foo.name
  puts foo.bars.count
end

如何避免我的聚合上的N+1 problem?换句话说,我不希望每行都有一个新的SELECT COUNT(*)...查询。我可以简单地创建一个SQL视图并将其映射到一个新模型,但是有一个更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

DataMpper对这些事情反复无常,所以我会给你一些选项,可以根据你的真实代码看起来有用。

  1. 只需将count更改为size,即put foo.bars.size。 DM的战略急切加载有时可以使用这种方法。

  2. 在@ foos.each循环之前强制加载,并将计数更改为大小,例如

    @foos = Foo.all(...)
    @foos.bars.to_a
    @foos.each do | foo |
      puts foo.name
      puts foo.bars.size
    end
    
  3. 在@ foos.each循环之前发出一个原始SQL查询,它返回带有foo id和bar计数的结构,#map将它们转换为一个Hash by food id并将它们放入循环中。 (我只需要一次或两次使用这种级别的废话,我建议在它之前摆弄#1和2。)