2017-12-30 62 views
2

가정하자 내가 가진이 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); 

그러나 마지막 스레드 객체가 latestPost 기록되어 있습니다. Eloquent를 사용하면서이 쿼리를 어떻게 최적화 할 수 있습니까? 당신은 레코드를 제한하기 위해 thread_idgroup by을 던지는 시도 할 수

감사

+1

이 질문에 대한 답변도 알고 싶습니다. 이론적으로는 관계를 미리로드하지 않으면 자원이 적게 듭니다 (20 개의 스레드를 나열하면 21 개의 쿼리 만 사용한다고 가정) – ahmad

+0

그래, 이런 종류의 작업에 ORM을 사용하면 의도하지 않은 질의의 폭발. 이것은 종종 N + 1 문제라고합니다. Laracast의 [The N + 1 Problem] (https://laracasts.com/lessons/eager-loading)을 참조하십시오. –

답변

1

스레드 당 1로 돌아왔다.

예로 posts 관계를 사용 : 당신은 쿼리 DB::select 통해 만 thread_id 당 1 개 레코드를 반환해야한다는 실행하면

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

: 열망 로딩

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

쿼리 로그. 즉, 불필요한 모델을 수화하여 부모 당 1 명과 일치시킬 필요가 없음을 의미합니다. 부모 당 최대 1 명으로 시작합니다.