3

我有一个页面需要很长时间才能呈现出来。一半的时间(3 秒)花在一个 .find 调用上,该调用有一堆急切加载的关联。我真正需要的是每种情况下关联记录的数量,以显示在表格中:我不需要实际记录本身。有没有办法只是急切地加载计数?这是一个简化的示例:

@subjects = Subject.find(:all, :include => [:questions])

在我的表格中,对于每一行(即每个主题),我只显示主题字段的值以及每个主题的相关问题的数量。我可以优化上述 find 调用以满足这些要求吗?

我考虑过使用组字段,但我的完整调用包含一些不同的关联,以及一些二阶关联,所以我认为 group by 不会起作用。

@subjects = Subject.find(:all, :include => [{:questions => :tags}, {:quizzes => :tags}], :order => "subjects.name")

:tags 在这种情况下是一个二阶关联,通过标记。这是我的联想,以防不清楚发生了什么。

Subject
  has_many :questions
  has_many :quizzes

Question
  belongs_to :subject
  has_many :taggings
  has_many :tags, :through => :taggings

Quiz
  belongs_to :subject
  has_many :taggings
  has_many :tags, :through => :taggings

感谢任何建议 - 最大

4

3 回答 3

3

我相信最好的方法是使用:counter_cache关联belongs_to

class Subject < ActiveRecord::Base
  has_many :questions
end

class Question < ActiveRecord::Base
  belongs_to :subject, :counter_cache => true
end

要使用counter_cache,您还需要在表格中添加一questions_countsubjects

来自railsapi.com

:counter_cache
通过使用 increment_counter 和 decrement_counter 缓存关联类上的所属对象的数量。计数器缓存在创建此类对象时递增,在销毁时递减 [...]

于 2010-05-12T13:11:31.943 回答
1

您可以为此目的实现计数器缓存。我在相册模型上维护了一个计数器,用于跟踪与之关联的照片数量。我的过程看起来有点像这样(我相信我在某处的博客上找到了这个方法,所以我不相信原始代码):

在照片模型上:

after_save :update_counter_caches
after_destroy :update_counter_caches

def update_counter_caches
  self.albums.each { |a| a.update_count } unless self.albums.empty?
end

在专辑模型上:

def update_count
  update_attribute(:photographs_count, self.photographs.length)
end

您在相册中需要的迁移:

class AddCounterCacheColumnToModels < ActiveRecord::Migration
  def self.up
    add_column :albums, :photographs_count, :integer, :default => 0
  end

  def self.down
    remove_column :albums, :photographs_count
  end
end

除非我误解了您的问题,否则这应该是实现您想要的一种非常简洁的方式。它在我当前的项目中运行良好。:)


编辑:作为一个注释,我使用这个设置而不是默认的 :counter_cache 方法的原因是因为我需要为一个模型上的多个关联维护多个计数器。据我所知,您无法使用 :counter_cache 来实现。

于 2010-05-12T11:50:13.447 回答
0

我认为最快的方法:

@subjects = Subject.count(:joins => :questions, :select => 'DISTINCT(questions.id)')

而且我不确定更复杂的查询(未测试):

@subjects = Subject.count(:joins => [{:questions => :tags}, {:quizzes => :tags}], :select => 'DISTINCT(tags.id)'
于 2010-05-12T12:50:01.780 回答