嵌套模型的计数总和

Sum of counts for nested models

我有两个模型:CategoryAd类别has_many:广告 + 我添加了计数器缓存:ads_count。我使用 gem awesome_nested_set 来制作嵌套类别,因此 Category1 可以是 Category2 的 parent/child,它可以是 Category3 的父级等。我需要什么我的类别#index 是计算属于特定类别或子类别(或 "grandchild" 等)的广告总和。我现在的解决方案是:some_nested_categories.sum(:ads_count)。但是假设如果我的索引页面中有很多类别,它会进行很多查询来检索所有这些数据并且花费的时间太长。我怎样才能更有效地做到这一点?感谢您的帮助!

您可以手动扩展 counter_cache 的想法以获得某种 sum_cache,让我们称之为 nested_ads_count

那么一般有4个case需要处理

  • 一个类别获得新的添加
  • 一个类别 "Moved/added" 到一个新的父类别
  • 类别被删除(或从父类别中删除)

一个 after_update 回调,当当前 nested_ads_countads_count 更新时更新父 nested_ads_count 的回调。解决了第一种情况。

awesome_nested_set解决了另外2个案例

使用 after_addafter_remove 回调重新计算 nested_ads_count

计算和缓存 nested_ads_count 的方法如下所示

def reset_nested_ads_count
  self.nested_ads_count = some_nested_categories.sum(:nested_ads_count) + self.ads_count
end

当计数的使用频率大于它的更新频率时,此方法是最佳的,因为它只在需要更新数字而不是需要更新数字时进行耗时的查询看过。

可能会发生一个陷阱,那就是如果你的嵌套中有一个循环(a > b > a,或者更隐蔽的 a > b > c > ... > a),你可以得到自己陷入无限循环。我没有看到任何明确说明 awesome_nested_set 阻止这种情况。