我有两个表:
线程
id, created_at, updated_at, deleted_at
消息
id, thread_id, user_id, created_at, updated_at, deleted_at
以下是我创建的建立这种关系的SQL Fiddle的链接:
http://sqlfiddle.com/#!9/915829/3/0
线程模型与消息具有这种关系
/**
* Messages relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*
* @codeCoverageIgnore
*/
public function messages()
{
return $this->hasMany(Message::class, 'thread_id', 'id');
}
消息模型与线程具有这种关系:
/**
* Thread relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*
*/
public function thread()
{
return $this->belongsTo(Thread::class, 'thread_id', 'id');
}
我首先运行一个查询,该查询获取特定用户的所有线程。一旦获得所有线程,就将每个线程的ID提取到数组中。现在,我想获取每个线程ID的最新消息。我已经尝试过:
Message::whereIn('thread_id', $threadIds)
但是这给了我与每个thread_id相关的每条消息,看着我发现,如果说几个线程有成千上万条与之相关的消息,这可能会引起一些重大问题。我还尝试了以下方法:
Message::whereIn('thread_id', $threadIds)->take(1)
仅返回一个我也不想要的结果。我想知道是否有人知道仅为每个$ threadIds获取最新消息的方法。
这是我的架构示例,其中包含一些示例数据:
CREATE TABLE `messages` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`thread_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`body` text COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `threads` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`subject` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `threads` (`id`, `subject`, `created_at`, `updated_at`, `deleted_at`)
VALUES
(1, 'test subject 1', '2019-02-01 00:32:56', '2019-02-01 00:32:56', NULL),
(2, 'test subject 2', '2019-02-01 00:34:42', '2019-02-01 00:34:42', NULL);
INSERT INTO `messages` (`id`, `thread_id`, `user_id`, `body`, `created_at`, `updated_at`, `deleted_at`)
VALUES
(1, 1, 2, 'test1', '2019-02-01 00:32:56', '2019-02-01 00:32:56', NULL),
(2, 1, 1, 'test2', '2019-02-01 00:32:59', '2019-02-01 00:32:59', NULL),
(3, 1, 2, 'test3', '2019-02-01 00:34:42', '2019-02-01 00:34:42', NULL),
(4, 2, 1, 'test4', '2019-02-01 00:35:56', '2019-02-01 00:35:56', NULL),
(5, 2, 3, 'test5', '2019-02-01 00:36:59', '2019-02-01 00:36:59', NULL),
(6, 2, 1, 'test6', '2019-02-01 00:37:42', '2019-02-01 00:37:42', NULL);
假设我要获取ID为1和2的线程的最新消息,我想要这样的结果集:
id thread_id user_id body created_at updated_at deleted_at
3 1 2 test3 2019-02-01T00:34:42Z 2019-02-01T00:34:42Z (null)
6 2 1 test6 2019-02-01T00:37:42Z 2019-02-01T00:37:42Z (null)
我一直在网上寻找类似的问题,但在堆栈溢出here上发现了一个非常相似的问题,但不幸的是,它没有得到回答。预先感谢任何愿意回答这个问题的人。
答案 0 :(得分:0)
我不确定这是否是最佳方法。但是我尝试了并且成功了。
我的方法是在获取threadIds数组之后,我运行一个循环并获取每个线程的最新消息。然后,我将该消息存储在另一个数组中。
$messages = array();
foreach($threadIds as $threadId)
{
$message = Message::where('thread_id', $threadId)
->whereNotNull(`deleted_at`)
->orderby('created_at','desc')
->first();
$messages[] = $message;
}
dd($messages);