【问题标题】:Optimal way to find intersection in Laravel在 Laravel 中找到交叉点的最佳方法
【发布时间】:2020-04-26 09:43:37
【问题描述】:

我在 Laravel 应用中有用户和聊天模型。用户可以成为许多聊天的成员,所以我在聊天和用户之间有多对多的关系 - 使用belongsToMany

假设我知道的用户 ID 很少,我想检索所有普通聊天(他们同时是成员的聊天,例如,所有具有给定 ID 的用户分组)。这个查询应该如何使用 Laravel 构建?

【问题讨论】:

    标签: php mysql laravel eloquent


    【解决方案1】:

    最好的方法是加入:

    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));
    

    这仍然只执行一个查询,但连接了数据透视表和用户表。

    【讨论】:

    • 谢谢,但似乎我得到了所有列出的用户是成员的聊天,但不是所有的聊天都同时是成员。也许我的问题不准确
    • 你能分享更多关于你的结构的细节吗?据我了解,您的意思是您想要所有成员同时参与的聊天? (例如在群聊中?)
    • 这正是我想要的。我有带有 user_id 和 chat_id 字段的用户、聊天表和 user_chats 表
    • 尝试更新。 whereIn 的行为类似于 OR,但使用一系列条件执行 where([...]) 的行为应该类似于 AND
    • 我添加了缺少的括号和 ;在两个查询中并更新它们以匹配表名 - 但都失败了
    【解决方案2】:

    你可以使用:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-13
      • 2011-02-02
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      • 2012-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多