You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8中如何按from_user_id和to_user_id分组获取唯一会话?

方案一:无需修改表结构,查询时生成统一会话标识

核心逻辑是通过数据库内置函数将两个用户ID按固定顺序排序,生成同一对话的唯一标识,避免收发顺序不同导致分组拆分。
大多数关系型数据库都支持LEAST()(取多个值的最小值)和GREATEST()(取多个值的最大值)函数,不管消息收发方向如何,同一对用户生成的两个值组合完全一致。
对应的Laravel查询构造器写法如下:

->selectRaw('LEAST(from_user_id, to_user_id) as session_user1, GREATEST(from_user_id, to_user_id) as session_user2, MAX(created_at) as latest_msg_time, id, content')
->where(function($q) use($user_id) {
       $q->where('from_user_id', $user_id)
       ->orWhere('to_user_id', $user_id);
})
->groupBy('session_user1', 'session_user2')
->orderBy('latest_msg_time', 'desc');

注意:如果数据库开启了严格模式,需要调整select的字段规则,或者先通过子查询按消息时间倒序排列后再分组,确保拿到的是每个会话最新的消息。
该方案适配快速上线需求,缺点是分组时需要做字段计算,无法走索引,数据量超过十万级后查询性能会明显下降。

方案二:调整为会话+消息的二级表结构(推荐长期使用)

这是聊天系统的标准设计,从表结构层面解决会话唯一的问题,后续扩展也更灵活:

  1. 新增conversation会话表,核心字段:
    • id 主键
    • user_min_id 两个用户ID的较小值
    • user_max_id 两个用户ID的较大值
    • latest_msg 最新消息预览
    • latest_msg_at 最新消息时间
    • unread_count 未读消息数(可按用户维度拆分存储)
    • 可扩展置顶、免打扰等会话属性
  2. 原有消息表改为conversation_message,新增conversation_id关联会话表,保留原有收发人、内容、时间等字段。

新增消息时先查询对应会话是否存在,不存在则创建,存在则更新会话的最新消息、时间等字段。查询会话列表时直接从conversation表筛选包含当前登录用户的记录即可,不需要分组计算,性能远高于单表方案,也不会出现会话重复的问题。

内容的提问来源于stack exchange,提问作者Devsi Odedra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 00:06:04