Оптимальный способ найти пересечение в Laravel - PullRequest
5 голосов
/ 26 апреля 2020

У меня есть пользователь и модель чата в приложении Laravel. Пользователь может быть участником многих чатов, поэтому я имею отношение многие-ко-многим между чатами и пользователями - используется belongsToMany.

Допустим, я знаю несколько идентификаторов пользователей и хочу получить все общие чаты (чаты, в которых они одновременно являются участниками, например групповые чаты, где все пользователи с указанными идентификаторами сгруппированы в). Как этот запрос должен быть построен с использованием Laravel?

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Самым оптимальным способом было бы сделать объединение:

Chat::join('chat_user', 'chat_id', 'chats.id')
   ->whereIn('chat_user.user_id',$listOfUserIds)
   ->selectRaw('chat_user.chat_id, COUNT(1) as users_count')
   ->groupBy('chat_user.chat_id')
   ->having('users_count','=', count($listOfUserIds));

Это оптимально, потому что оно присоединяется только к стержню.

Хотя элегантный способ сделать это - использовать whereHas с параметрами "кардинальности", т. Е. Найти все чаты, в которых участвуют эти пользователи, пока все они задействованы.

Chat::whereHas('user', function ($q) {
    return $q->whereIn('id', $listOfUserIds);
}, '=', count($listOfUserIds));

это все еще выполняет только один запрос, но объединяет сводку и таблица пользователей.

1 голос
/ 26 апреля 2020

Вы можете использовать:

    $membersWithChats = Member::whereIn('id', $listOfIDs)->with('chats')->get();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...