是否可以在 Laravel 8 中按 from 和 to user id 分组
Posted
技术标签:
【中文标题】是否可以在 Laravel 8 中按 from 和 to user id 分组【英文标题】:Is it possible to grouping by from and to user id in Laravel 8 【发布时间】:2021-12-06 22:53:07 【问题描述】:我有一对一的聊天简单表,其中消息存储从用户 ID 到用户 ID。这是架构。
我通过将 from_user_id 匹配与登录用户或 to_user_id 匹配来检索两个用户之间的对话
->where(function($q) use($user_id)
$q->where('from_user_id', $user_id)
->orWhere('to_user_id', $user_id);
)
现在我想要登录用户和其他用户之间的独特对话。我试过了
->groupBy('from_user_id', 'to_user_id')
但它同时返回记录 ID:1 和 6,因为它存储为 65 - 66 和 66 - 65。
因此,我可以通过独特的对话进行分组并仅获得一条记录。或者我需要将表的架构更改为会话和会话消息。
请指导我。 谢谢。
【问题讨论】:
您可以按原始表达式进行分组,例如(调整语法)->groupBy(db::RAW('LEAST(from_user_id,to_user_id), GREATEST(from_user_id,to_user_id)'))
。
@Akina 非常感谢。它给出了唯一的记录,但是从那个重复的记录 order by 不起作用,是否可以从相同的记录中获取最新记录?
使用显示的分组获得组的最大日期时间。使用它作为子查询从另一个表副本中选择相应的行。这在纯 SQL 中很简单——但我不使用 Laravel,因此我不知道它会是什么样子(也许 Laravel 有一些特殊的工具来简化这个常见任务)。
【参考方案1】:
我建议添加一个对话模型。基本上,您需要为每个用户到用户的关系(以及其中的所有消息)设置一个唯一标识符,而对话模型将是实现这一目标的最简洁的方法。
话虽如此,有一些聪明的方法可以在没有额外模型的情况下做你想做的事。由于您知道登录用户的 ID,因此您可以将回调传递给 Collection 的 groupBy 方法,该方法按 不是登录用户的 ID 分组。例如:
->where(function($query)
$query->where('from_user_id', $user_id)
->orWhere('to_user_id', $user_id)
)
// So the messages appear in order.
->orderByDesc('created_at')
->get()
->groupBy(function($item) use ($user_id)
// If the message was sent by the user, it groups on the recipient's ID.
// If the message was received by the user, it groups on the sender's ID.
return $item->from_user_id == $user_id ? $item->to_user_id : $item->from_user_id;
);
此示例未考虑用户向自己发送消息(这可能在您的系统中),因此可能需要微调。
【讨论】:
感谢@James 的回复,我知道第一次谈话的事情。但它已经开发了,所以找到了解决方案。您的第二个答案不起作用,它对数据进行分组,但在组内提供所有记录。我想在查询组中而不是在集合中。 不要计划拥有数百万行; "or" 的表现不好。【参考方案2】:最近,我为我的公司编写了一个聊天系统。我尝试了许多模式,但最终找到了最好的一个。我可以和你分享。
此架构可能包含多个表,并会迫使您发送更多请求。但在这种结构中,您将能够轻松处理所有任务。这是模型和控制器结构:
聊天消息:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ChatMessage extends Model
use HasFactory;
public $table = "chat_messages";
protected $fillable = ['chat_id', 'user_id','content'];
public function chat()
return $this->belongsTo(ChatUser::class, 'chat_id', 'id');
public function user()
return $this->belongsTo(User::class);
聊天用户:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ChatUser extends Model
use HasFactory;
public $table = "chat_users";
protected $fillable = ['user_id_from', 'user_id_to','last_activity'];
protected $dates = ['last_activity'];
public function user_from()
return $this->belongsTo(User::class, 'user_id_from', 'id');
public function user_to()
return $this->belongsTo(User::class, 'user_id_to', 'id');
public function messages()
return $this->hasMany(ChatMessage::class, 'chat_id', 'id')->latest('id')->take(15);
聊天控制器:
public function index()
$chats = ChatUser::has('messages')
->where('user_id_from', $this->user->id)
->orWhere(function ($query)
$query->where('user_id_to' , $this->user->id);
)
->with(['user_to','user_from'])
->orderBy('last_activity', 'DESC')
->get();
return $this->successResponse(new ChatCollection($chats));
如果您有任何问题,请不要犹豫。
【讨论】:
正确。我有相同的群聊结构。和工作发现。我只是想要如上所述,因为它已经构建了架构,这就是原因。 老实说,我首先尝试使用您的结构。但我意识到处理它非常困难。这就是为什么我建议你改变结构。数据库对组和私有使用相同的结构会很好。以上是关于是否可以在 Laravel 8 中按 from 和 to user id 分组的主要内容,如果未能解决你的问题,请参考以下文章