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 个表的查询都可以有一个索引来帮忙。实际的索引实现取决于您,取决于您的应用程序的具体情况(读写负载、表大小、基数等)
此处涉及三个模型: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 个表的查询都可以有一个索引来帮忙。实际的索引实现取决于您,取决于您的应用程序的具体情况(读写负载、表大小、基数等)