У меня есть 4 таблицы, которые связаны в базе данных и в моделях следующим образом:
Users (hasMany(communities), hasMany(comments), hasMany(submissions))
Communities (belongsTo(user), hasMany(submissions))
Submissions (belongsTo(community), belongsTo(user), hasMany(comments))
Comments (belongsTo(user) , belongsTo(submission))
Сейчас. Если я использую отношения, чтобы получить, скажем 25 последних представлений, как это:
$submissions = Submission::simplePaginate(25);
У меня 76 выполненных запросов после использования foreach для просмотра результатов.
Если я использую готовую загрузку со следующим
$submissions = Submission::with(['user', 'community', 'comments'])->simplePaginate(25);
Я получил 4 запроса, что является оптимальным (я думаю).
Теперь моя проблема в том, что в сообществах у меня есть поле базы данных с именем active, которое принимает 1 для активного сообщества и 0 для неактивного. Как вы уже догадались, предыдущий запрос возвращает все, включая неактивные сообщества.
Я думал об ограничениях загрузки, поэтому я использовал следующее:
$submissions = Submission::with([
'community' => function($query) {
$query->active();
}
]
)->with(['user', 'comments'])->simplePaginate(25);
Это все еще делает эту работу с 4 запросами, но теперь я столкнулся с другой проблемой. Этот метод фильтрует неактивные сообщества, но по-прежнему загружает сообщения, пользователей и комментарии. И теперь я остаюсь с результатом, где я получаю сообщения от неактивных сообществ.
Наконец, после прочтения этого сообщества я попытался сделать следующее:
$submissions = Submission::whereHas(
'community', function($query) {
$query->active();
}
)->with(['user', 'comments'])->simplePaginate(20);
Таким образом, вместо использования -> with () я использовал -> whereHas (), как кто-то предложил. Однако, хотя это дает правильные результаты, т. Е. Дает мне сообщения, комментарии и пользователей только из активных сообществ, теперь оно делает это в 23 запросах, в соответствии с отзывами, полученными от Laravel Debugbar.
Это нормально? Это единственный способ сделать это через Eloquent без написания пользовательских запросов с объединениями? Дует ли я 23 запроса непропорционально?
Любая помощь будет принята с благодарностью.
Ваша проблема в том, что active()
Область действия выполняет запрос для каждого сообщества, которое вы извлекаете, в вашем случае 20.
Чтобы оптимизировать это, вы можете сделать конкретные отношения в Submission
модель, в которой вы активно фильтруете активные сообщества.
// Submission model
public function activeCommunities (){
return $this->hasMany(Community::class)->whereActive(true);
}
Теперь ваш запрос будет выглядеть так:
$submissions = Submission::with(['user', 'comments', 'activeCommunities])
->simplePaginate(25);
Это должно выполнить 4 запроса, я считаю.
Надеюсь, это поможет вам.
Итак, немного поработав, я нашел решение, но я все еще не уверен. Я публикую это для дальнейшего использования, так как это решило мою проблему. Код, который я использовал, следующий
$submissions = Submission::whereHas(
'community', function($query) {
$query->where('is_active', true);
}
)->with(['user', 'community'])->withCount('comments')
->paginate(25);
Итак, я попытался с помощью whereHas()
проверить существование моделей, прежде чем загружать community
модель, если это имеет смысл? Похоже, я получил желаемые результаты, поскольку теперь я выполняю всего 4 запроса, чтобы получить все представленные материалы и связанную с ними информацию, фильтруя неактивные сообщества.