ActiveRecord查询过滤嵌套模型

时间:2013-04-11 19:59:08

标签: ruby-on-rails ruby activerecord

说我有以下型号

Course has_many :students
Course has_many :lectures
Lecture has_many :topics

如果我这样做:

courses = Course.find(:all, :includes => [:students, {:lectures => :topics}])

我得到所有课程,学生,讲座和主题。

我想只获得有某些学生的课程,然后对于每门课程,只希望得到一些讲座,但每个讲座的所有主题。

所以说我希望得到一个名为'John'的学生的所有课程,但只有这两门课程的最近2个讲座以及这2个讲座的所有主题。

我不明白如何将这些过滤器应用于上面的原始查询。

非常喜欢有关如何执行此类查询的指导。

1 个答案:

答案 0 :(得分:0)

您可以使用查询API修改急切加载的内容:

courses = Course.includes(:students, {:lectures => :topics}).
                 where(:students => {:name => 'John'})

获取每门课程最近的两个课程是一项重大挑战,我不相信有一个跨数据库解决方案可以做到这一点,没有递归子查询来确定排名(这将是一个主要的性能消耗对于非平凡数量的数据并取消预先加载的任何好处)。您可以确定最近的(MAX),然后是最后一次(MAX,早于原始MAX),但这种方法也会非常低效且非常混乱。

如果您可以选择特定的DBMS,这可能是可行的。或者,选择不同的策略来确定“最近”(例如,每个课程的缓存日期,或者通过的固定时间)。

<强>更新

假设您只需加载所有讲座并手动选择前2名即可,您可以使用as_json序列化程序执行此操作(对于JSON):

courses = ... # same as above
courses.each do |c|
  c.lectures = c.lectures.sort_by(&:happens_at)[-1..-2]
end.as_json(:include => [:students, {:lectures => {:include => :topics}}])