Rails: собирать записи, таблицы соединений которых появляются в двух запросах - PullRequest
1 голос
/ 14 июня 2019

Здесь есть три модели: Цель, Студент и Семинар.Все они связаны с has_and_belongs_to_many.

Существует модель соединения ObjectiveStudent, которая включает столбцы «ready» и «points_all_time».Существует модель соединения 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 соответственно.Моя конечная цель состоит в том, чтобы собрать цели, которые отвечают всем вышеперечисленным критериям.

Или я все это неправильно подхожу?

Дополнительный вопрос: я также хотел бы отсортировать цели по их приоритетности на данном семинаре.Но я боюсь, что это добавит слишком много к загрузке базы данных.Что вы думаете об этом?

Заранее благодарим вас за понимание.

1 Ответ

2 голосов
/ 14 июня 2019

Чтобы получить 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 запросов к таблицам могли иметь помощь в индексе.Реальная реализация индекса зависит от вас и зависит от специфики вашего приложения (нагрузка чтения - записи, размер таблиц, количество элементов и т. Д.)

...