Rails:收集其连接表出现在两个查询中的记录

Rails: Collect records whose join tables appear in two queries

此处涉及三个模型:Objective、学生和研讨会。所有都与 has_and_belongs_to_many.

关联

有一个 Objective 学生加入模型,其中包括列 "ready" 和 "points_all_time"。有一个包含列 "priority" 的 Objective 研讨会加入模型。

我需要收集与给定学生和给定研讨会相关的所有目标。

他们还需要在研讨会中用零以上的 "priority" 标记。所以我想我需要这一行:

obj_sems = ObjectiveSeminar.where(:seminar => given_seminar).where("priority > ?", 0)

最后,他们还需要成为学生准备好的目标,但没有超过 7 分。所以我想我需要这条线:

obj_studs = ObjectiveStudent.where(:user => given_student, :ready => true).where("points_all_time <= ?", 7)

有没有一种方法可以收集所有在上述两个查询中都出现 join table 记录的目标?请注意,这两个列表都没有 return 目标;他们分别 return objective_seminars 和 objective_students。我的最终目标是收集满足上述所有条件的目标。

还是我的做法全错了?

奖金问题:我也很想根据给定研讨会中的优先级对目标进行排序。但恐怕这会增加太多数据库负载。您对此有何看法?

提前感谢您的任何见解。

为了获得 Objectives,您需要从那里开始查询。 为了使用 AND 条件查询关联表,您需要对这些表进行内部联接。 最后,您需要一个 distinct 运算符来只获取每个 objective 一次。

你需要的(我认为)扩展版本是:

Objective.joins(objective_seminars: :seminar, objective_student: :student).
  where(seminars: seminar_search_params, strudents: student_search_params).
  where('objective_seminars.priority > 0').
  where('objective_students.ready = 1 AND points_all_time <= 7').
  order('objective_seminars.priority ASC').
  distinct

现在,对于数据库负载,这完全取决于您的索引和表的大小。 上面的查询将转换为以下 SQL(或类似的东西)。

SELECT DISTINCT objectives.* FROM objectives
  INNER JOIN objective_students ON objective_students.objective_id = objectives.id
  INNER JOIN students ON students.id = objective_students.student_id
  INNER JOIN objective_seminars ON objective_seminars.objective_id = objectives.id
  INNER JOIN seminars ON seminars.id = objective_seminars.seminar_id
  WHERE seminars_query AND
    students_query AND
    objective_seminars.priority > 0 AND
    objective_students.ready = 1 AND points_all_time <= 7 AND
    objective_seminars.priority ASC

因此您需要添加或扩展索引,以便所有 5 个表的查询都可以有一个索引来帮忙。实际的索引实现取决于您,取决于您的应用程序的具体情况(读写负载、表大小、基数等)