Laravel中查找交集的最佳方式

5

我在 Laravel 应用程序中有 User 和 Chat 模型。用户可以是许多聊天的成员,因此我在聊天和用户之间有多对多关系 - 使用 belongsToMany

假设我知道几个用户 ID,并且我想检索所有 共同的聊天 (这些聊天中它们同时为成员,例如,所有 具有给定 ID 的用户都聚集在其中的群聊)。如何使用 Laravel 构建此查询?

2个回答

2
最优的方式是进行连接操作:
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));

这仍然只执行一个查询,但连接了中间表和用户表。

谢谢,但似乎我得到的是所有列出用户为成员的聊天记录,而不是他们同时为成员的所有聊天记录。也许我的问题不太准确。 - moonvader
你能分享更多关于你的结构的细节吗?据我理解,你的意思是想要所有成员同时参与的聊天吗?(例如像在群聊中一样?) - apokryfos
这正是我想要的。我有用户(users),聊天(chats)表,以及带有 user_id 和 chat_id 字段的用户聊天(user_chats)表。 - moonvader
尝试更新。 whereIn 的行为类似于 OR,但使用条件数组进行 where([...]) 应该像 AND 一样运作。 - apokryfos
我在两个查询中添加了缺失的括号和分号,并更新它们以匹配表名 - 但是两者都失败了。 - moonvader
抱歉有点匆忙。这是第一个版本,但要确保找到的匹配用户数量应该是我们正在寻找的所有用户。希望这个版本能够工作。 - apokryfos

1

您可以使用:

    $membersWithChats = Member::whereIn('id', $listOfIDs)->with('chats')->get();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接