#mysql #laravel #eloquent #relationship
#mysql #laravel #eloquent #отношения
Вопрос:
У меня есть интерфейс, который отображает список сообществ на платформе. В сообществах есть участники, и, в свою очередь, участники / профили могут дружить друг с другом. На странице со списком каждой карточки сообщества должно отображаться количество участников (в сообществе) и количество друзей (друзья, зарегистрированные в профиле) из этих участников.
Вот иллюстрация того, как выглядит карточка сообщества
Сначала я получаю сообщества с участниками:
$communities = $loggedInProfile->communities->load('members')->take(15);
А затем перебор сообществ, а затем участников, чтобы выяснить, какие из них являются друзьями зарегистрированного пользователя.
foreach ($communities as $key => $community) {
$friends = [];
foreach ($community->members as $member) {
if ($loggedInProfile->isFriendWith($member)) {
array_push($friends, $member);
}
}
$community->members_who_are_friends = $friends;
}
Моя проблема в том, что это очень обременительно с точки зрения количества запросов, когда ассоциации становятся большими. Есть ли лучший способ получения этих отношений без использования вложенных циклов for? Я также индексирую все данные с помощью Elasticsearch. Будет ли поиск такого рода лучше с помощью Elasticsearch? Также было бы это хорошим вариантом использования для hasThrough
?
Обновить
members
Отношения:
public function members()
{
return $this->belongsToMany('AppProfile', 'community_members', 'community_id', 'profile_id')->withTimestamps();
}
isFriendWith
Отношения:
public function isFriendWith(Model $recipient)
{
return $this->findFriendship($recipient)->where('status', Status::ACCEPTED)->exists();
}
Проверка выполняется в таблице с именем friendships
. status
Столбец (который может быть либо 0, либо 1) проверяется, чтобы увидеть, есть ли друзья или нет.
findFriendship
Проверка:
private function findFriendship(Model $recipient)
{
return Friendship::betweenModels($this, $recipient);
}
Структура базы данных:
-Миграция профилей
Schema::create('profiles', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
-Миграция сообществ (внешний ключ является owner
сообщества)
Schema::create('communities', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('profile_id');
$table->foreign('profile_id')->references('id')->on('profiles');
$table->string('slug')->unique();
});
-Миграция Community_members
Schema::create('community_members', function (Blueprint $table) {
$table->primary(['profile_id', 'community_id']);
$table->unsignedInteger('profile_id');
$table->foreign('profile_id')->references('id')->on('profiles');
$table->unsignedInteger('community_id');
$table->foreign('community_id')->references('id')->on('communities');
$table->timestamps();
});
-Миграция дружеских отношений
Schema::create('friendships'), function (Blueprint $table) {
$table->increments('id');
$table->morphs('sender');
$table->morphs('recipient');
$table->tinyInteger('status')->default(0);
$table->timestamps();
});
Комментарии:
1. можете ли вы показать мне функцию getMutualFriends ? какое поле $member вы там используете?
2. Извините за это, я использовал неправильную проверку на дружбу. Обновил вопрос. Участник — это член сообщества, которое я просматриваю. Я перебираю отношения members () в сообществе.
3. покажите мне
function isFriendWith($member)
или просто скажите мне, какое поле $ member вы используете, чтобы узнать, взаимно ли это4. Обновленный вопрос.
5. участник — это экземпляр пользователя, верно? то же, что и loggedUser ..
Ответ №1:
В вашей строке:
$communities = $loggedInProfile->communities->load('members')->take(15);
load()
используется для выполнения отложенной загрузки, т. Е. вы загружаете участников после извлечения сообществ, что приводит к различным запросам для каждого сообщества. Вы могли бы извлечь все данные с помощью одного запроса с помощью with()
. Кроме того, take(15)
выполняется для результирующей коллекции, а не для запроса. Попробуйте это:
$communities = $loggedInProfile->communities()->with('members')->take(15)->get();
Комментарии:
1. Я попробовал оба подхода, и, похоже, это не влияет на количество выполняемых запросов :/.