在同一个对象中获取具有最新Post的线程,latest()会产生巨大的开销

问题描述 投票:2回答:1

假设我的模型名为Thread.php:

public function post()
{
    return $this->hasMany('App\Post');
}

public function latestPost()
{
    return $this->hasOne('App\Post')->latest('id');
}

我有一个页面显示所有线程及其最新帖子。为此,我做了类似的事情

all_threads = Thread::with('latestPost')->get();

它执行此查询:

select * from `posts` where `posts`.`thread_id` in ('1', '2', '3', '4', '5', '6', '7', '8', '9', '10') order by `id` desc

它有效,但是latestPost()正在抓取表格中的所有帖子,每个帖子,然后返回最新的帖子。这会产生数以千计的不必要的对象,并且开销已经很高。

理想的是只采取最新的Post记录,但我不知道如何使用Eloquent。

我尝试过以下方法:

return $this->hasOne('App\Post')->orderBy('id', 'desc')->limit(1);
// or
return $this->hasOne('App\Post')->latest('id')->take(1);

但是只有最后一个Thread对象带有latestPost记录。如何在使用Eloquent的同时优化此查询?

谢谢

php mysql laravel laravel-5
1个回答
1
投票

您可以尝试在group by上投掷thread_id以限制每个线程返回1的记录。

posts关系为例:

$threads = Thread::with(['posts' => function ($q) {
    $q->groupBy('thread_id');
})->get();

查询日志以获取预先加载:

"select * from "posts" where "posts"."thread_id" in (?) group by "thread_id""

如果您通过DB::select运行该查询,它应该只返回每个thread_id 1条记录。这意味着它不需要将不需要的模型水合成每个父母只匹配1个,因为每个父母只需要1个最大值。

© www.soinside.com 2019 - 2024. All rights reserved.