根据Rails中has_many关系的计数选择流行的模型

时间:2009-11-12 01:41:04

标签: ruby-on-rails

我有两种模式:

Novel has_many :pages
Page belongs_to :novel

我想根据页数列出流行的小说。从本质上讲,我希望从此查询的结果中加载新模型:

select p.novel_id, count(*) as count
from pages p
GROUP BY p.novel_id
ORDER BY count DESC

我确信使用named_scope在Rails 2.3中有一些可爱的方法,但我无法让它工作。另外,如果它确实有效,它会慢慢变成狗吗?

我考虑过将page_count保留在Novel上,但这似乎违反了某些事情(惯例,规范化,我的灵魂)。

3 个答案:

答案 0 :(得分:5)

似乎计数器缓存是要走的路。如果在小说表(带索引)上创建一个名为page_count的列,Rails将缓存Novel模型本身的页数,使这种查询非常简单和高效。

named_scope模型上的Novel变为

class Novel < ActiveRecord::Base
  named_scope :popular, :order => 'page_count desc'
end

class Page < ActiveRecord::Base
  belongs_to :novel, :counter_cache => true
end

有关详细信息,请查看the counter cache railscast

答案 1 :(得分:2)

是的,那会很慢。在你的小说中缓存page_count并不是一件可怕的事情。规范化很好,直到它影响性能。

缓存昂贵的计算是大多数优化的本质。

答案 2 :(得分:1)

在此问题上保留counter_cache小说被视为可接受,并且应该有助于您的查询。

page.rb 中执行:

 belongs_to :novel, :counter_cache => true

novels表中添加pages_count列。创建页面时会自动递增,删除时会递减。