Laravel中如何查询仅匹配指定收件人集合的聊天消息
实现方案
要实现完全匹配指定用户集合的消息查询,需要同时满足两个条件:
- 消息的收件人包含所有指定的用户ID
- 消息没有指定用户ID之外的其他收件人
Laravel 7+ 可以通过组合whereHas和whereDoesntHave实现,代码如下:
$queryUserIds = [2,3]; $targetUserCount = count($queryUserIds); return Message::whereHas('recipients', function ($query) use ($queryUserIds) { $query->whereIn('userId', $queryUserIds); }, '=', $targetUserCount) // 要求正好匹配到所有目标用户,没有缺漏 ->whereDoesntHave('recipients', function ($query) use ($queryUserIds) { $query->whereNotIn('userId', $queryUserIds); }) // 排除包含目标用户之外的收件人的消息,没有多余用户 ->orderBy('id', 'DESC') ->get();
逻辑说明
你之前的whereIn写法只判断消息存在至少一个匹配的收件人,没有限制总数量和额外用户。上述代码的两个条件组合后,刚好实现完全匹配的效果,你举的示例中查询[2,3]时,会返回空结果,完全符合预期。
如果你的业务数据量较大,可以使用join+聚合的写法优化性能,避免两次子查询:
$queryUserIds = [2,3]; $targetUserCount = count($queryUserIds); return Message::join('recipients', 'messages.id', '=', 'recipients.messageId') ->groupBy('messages.id') ->havingRaw('COUNT(DISTINCT recipients.userId) = ?', [$targetUserCount]) ->havingRaw('SUM(CASE WHEN recipients.userId NOT IN (?) THEN 1 ELSE 0 END) = 0', [implode(',', $queryUserIds)]) ->orderBy('messages.id', 'DESC') ->get(['messages.*']);
内容的提问来源于stack exchange,提问作者Sylar
相关产品推荐
相关产品推荐

