2017-12-30 66 views
2

は私がThread.phpと呼ばれる私のモデルでこれを持っていると仮定します。が同じオブジェクト内にその最新の投稿とスレッドを取得する、最新の()は巨大なオーバーヘッドを作成

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

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

私はすべてのスレッドを表示するページを持っています彼らの最新の投稿。それは作品

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

が、latestPost()は、スレッドごとに、テーブル内のすべての記事をつかんで、その後、帰国されています。そうするために、私はそれは、このクエリを行いall_threads = Thread::with('latestPost')->get();

ような何かを最新のもの。これは、何千もの不要なオブジェクトを作成しており、オーバーヘッドはすでに高いです。

最新の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を使用してこのクエリを最適化するにはどうすればよいですか?あなたがスレッドごとに1に返されたレコードを制限するthread_idgroup byを投げてみてください

おかげ

+1

私はこの質問に対する答えも知りたいと思います。理論的には関係を事前にロードしないとリソースが少なくなります(20個のスレッドをリストすると21個のクエリしかないと仮定します) – ahmad

+0

ええ、この種の操作にORMを使用すると意図しないクエリの数の爆発。これはしばしばN + 1問題と呼ばれます。 Laracastの[The N + 1 Problem](https://laracasts.com/lessons/eager-loading)を参照してください。 –

答えて

1

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

あなたはDB::selectを経由してそのクエリを実行した場合、それが唯一のthread_idにつき1つのレコードを返すべきである:積極的なロードのため

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

クエリログ:一例としてposts関係を使用して

。つまり、最初に親に1つしかないので、不要なモデルを水分補給する必要はありません。

関連する問題