2015-08-22 12 views
0

В моем методе контроллера для представления индекса у меня есть следующая строка.Почему метод where() запускает SQL-запросы после того, как все вложенные отношения загружены?

@students_instance = Student.includes(:memo_tests => {:memo_target => :memo_level}) 

Таким образом, для каждых Student I нетерпеливых нагрузок всей необходимой информацией.

Позже в блоке .map я вызываю метод .where() в одном из соотношений, как показано ниже.

@all_students = @students_instance.map do |student| 

... 

last_pass = student.memo_tests.where(:result => true).last.created_at.utc 
difference_in_weeks = ((last_pass.to_i - current_date.to_i)/1.week).round 

... 

end 

Это приводит к одному запроса SQL для каждого student. И так как у меня более 300 студентов, это приводит к очень медленным временам загрузки и более чем 300 + SQL-запросам.

Я прав, полагая, что это вызвано методом .where(). Я думаю, это потому, что я проверил все остальное, и это две строки, которые вызывают все запросы.

Что еще более важно, есть ли лучший способ сделать это, который сводит эти запросы к одному запросу?

+0

Итак, вы хотите получить последний пройденный memo_test для каждого ученика? –

+0

Дело в том, что этот запрос будет довольно сложным, и я даже не уверен, что это можно сделать в ActiveRecord. Может быть, вам придется пойти на что-то вроде продолжения или написать sql самостоятельно –

+0

Не совсем, у меня уже есть доступ к «memo_tests» каждого ученика без выполнения запроса. Я хочу запустить метод '.where', не используя SQL-запрос. – nonsequiter

ответ

1

В тот момент, когда вы задаете вопрос where, инструкция переведена в запрос. Как правило, результат должен быть sql-кэшированным ...

В любом случае, чтобы быть уверенным, вы можете добавить логику программирования в свое утверждение. Таким образом, вы не запрашиваете NEW sql statement.

last_pass = student.memo_tests.map {|m| m.created_at if m.result}.compact.sort.last 

EDIT Я вижу вопрос в OP не требует сортировки ... Так, в результате чего сортировка:

last_pass = student.memo_tests.map {|m| m.created_at if m.result}.compact.last 

compact требуется удалить ноль результатов из массива.

+0

Это решение может быть еще медленнее этого оригинала. –

+0

Как? Если есть SQL, будет либо много, либо мало результатов ... Множество результатов, медленный sql, более медленная сортировка ... Немного результатов, быстрый sql, быстрая сортировка ... Нет SQL ... медленнее ??? –

+0

В оригинальном ответе вы сделали карту компактной и сортировали по коллекции неуточненной длины. Это редко бывает быстрее, чем sql, и, несмотря на непопулярность с людьми Rails, лучшим решением здесь является простое решение sql. –

 Смежные вопросы

  • Нет связанных вопросов^_^