Здесь важны три модели: объективная, студенческая и семинарская. Все они связаны с has_and_belongs_to_many.
Существует модель соединения ObjectiveStudent, которая включает столбцы «готово» и «точки_все_время». Существует модель соединения ObjectiveSeminar, которая включает столбец «приоритет».
Мне нужно собрать все цели, связанные с данным студентом, а также с данным семинаром.
Их также нужно отметить «приоритетом» выше нуля в семинаре. Поэтому я думаю, что мне нужна эта строка:
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)
Есть ли способ собрать все цели, чьи записи таблицы соединений появляются в обоих вышеуказанных запросах? Обратите внимание, что ни один из списков не возвращает цели; они возвращают target_seminars и target_students соответственно. Моя конечная цель — собрать цели, соответствующие всем вышеперечисленным критериям.
Или я подхожу ко всему этому неправильно?
Бонусный вопрос: я также хотел бы отсортировать цели по их приоритету в данном семинаре. Но я боюсь, что это слишком сильно увеличит нагрузку на базу данных. Что вы думаете об этом?
Заранее благодарим вас за любое понимание.
Чтобы получить Objectives
, вам нужно начать свой запрос с этого.
Чтобы запросить с условием AND
связанные таблицы, вам понадобятся внутренние соединения с этими таблицами.
Наконец, вам понадобится оператор distinct
, чтобы получить каждую цель только один раз.
Расширенная версия того, что (я думаю) вам нужно:
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 запросов к таблицам могли иметь индекс, помогающий. Фактическая реализация индекса зависит от вашего приложения (чтение-загрузка, размер таблиц, количество элементов и т. д.).
Это помогло мне достичь того, что мне было нужно. Сначала я получал сообщение об ошибке, что в задаче нет столбца «семинар». Но я смог это исправить, используя синтаксис кавычек во всех строках: where("objective_seminars.seminar_id == ?", Workshop.id). Спасибо.