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

发布于 2024-10-15 15:17:57 字数 370 浏览 1 评论 0原文

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

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

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

If I have a model of type Foo that has many child records of type Bar, I'd like to be able to show a list of Foo records and show the number of child Bar records. So I have something like...

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

How can I avoid the N+1 problem on my aggregates? In other words, I don't want a new SELECT COUNT(*)... query for each row. I could simply create a SQL view and map it to a new Model, but is there a simpler approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

︶ ̄淡然 2024-10-22 15:17:57

DataMpper 对这些事情变化无常,因此我将给您提供几个尝试的选项,这些选项可能会根据您的实际代码的外观而起作用。

  1. 只需将 count 更改为 size,即,puts foo.bars.size。 DM 的策略性预先加载有时可以使用这种方法。

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

    @foos = Foo.all(...)
    @foos.bars.to_a
    @foos.each 做 |富|
      放置 foo.name
      放置 foo.bars.size
    结尾
    
  3. 在 @foos.each 循环之前发出原始 SQL 查询返回带有 foo id 和 bar 计数的结构,#将它们按食物 id 映射到哈希中,并将它们放入循环中。 (我只需要诉诸这种级别的废话一两次,我建议在它之前摆弄 #1 和 2。)

DataMpper is fickle about these things so I'll give you a couple options to try that may work depending on what your real code looks like.

  1. Just change count to size, i.e., puts foo.bars.size. DM's strategic eager loading can sometimes work with this approach.

  2. Force an eager load before the @foos.each loop, and change count to size, e.g.

    @foos = Foo.all(...)
    @foos.bars.to_a
    @foos.each do | foo |
      puts foo.name
      puts foo.bars.size
    end
    
  3. Issue a raw SQL query before your @foos.each loop that returns structs with foo ids and bar counts, #map those into a Hash by food id and get them inside the loop. (I've only had to resort to this level of nonsense once or twice, I'd recommend fiddling with #1 and 2 for bit before it.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文