2014-03-06 70 views
0

我需要附加一個自定義選擇的雄辯查詢,但我發現整個事情有點難以理解。這涉及論壇系統,其中每個論壇對象需要知道註冊了多少個主題關係和評論關係。這是我到目前爲止有:優化雄辯查詢

在Forum.php

public function getNumTopics() { 
    return Topic::where('forum_id', '=', $this->id)->count(); 
} 

public function getNumComments() { 
    return Comment::wherein('topic_id', Topic::where('forum_id', '=', 1)->lists('id')); 
} 

控制器返回JSON

public function getCategories() { 
    $categories = ForumCategory::with('forums')->get(); 
    foreach ($categories as $cat) { 
     if ($cat->forums->count() > 0) { 
      foreach ($cat->forums as $forum) { 
       /* @var $forum Forum */ 
       $forum->num_topics = $forum->getNumTopics(); 
       $forum->num_posts = $forum->getNumComments(); 
      } 
     } 
    } 
    return Response::json($categories, 200); 
} 

通話時間約爲1300ms返回5分論壇三類別。我懷疑這是因爲這會執行大約16個查詢而不是一個。有沒有辦法將「num_topics」和「num_posts」附加爲select的屬性,以便我只執行一個查詢?

編輯

我基本上想要的是雄辯產生這樣的事情時,我問Forum::all()

select f.*, 
     ifnull(count(t.id), 0) num_topics, 
     ifnull(count(c.id), 0) num_posts 
    from forums f left join topics t on t.forum_id = f.id 
       left join comments c on c.topic_id = t.id 
group by f.id 
+0

我試圖優化的第一件事是getNumComments函數,它運行兩個查詢。另外你的getNumtTopics和getNumComments都運行基本相同的查詢,'Topic :: where('forum_id'...' –

+0

我已經添加了查詢,我想我想要雄辯爲我產生。 –

回答

1

你將要查詢這些表無論哪種方式,所以最好的辦法應該只是急於加載所有內容並在檢索後對其進行計數,而不是僅僅爲了查找計數而對數據庫進行更多調用。

public function getCategories() { 
    $categories = ForumCategory::with('forums.topics.comments')->get(); 
    foreach($categories as $category) { 
     foreach($category->forums as &$forum) { 
      $forum->num_topics = $forum->topics()->count(); 
      $forum->num_comments = 0; 
      foreach($forum->topics as $topic) { 
       $forum->num_comments += $topic->comments()->count(); 
      } 
     } 
    } 

    return Response::json($categories, 200); 
} 

這將附上num_topicsnum_comments每個Forum對象。

它的通話次數較少,但它在一次掃描中抓取更多信息,因此可能會更快或更慢,因此必須進行一些測試。好消息是,因爲它抓住了一切,所以不需要額外的查詢。

+0

對於大數據集(這可能成爲),像這樣查詢所有級別可能有點過分?或者是Laravel在內部進行一些優化,我在這裏沒有意識到?請參閱我希望在我的問題中產生的查詢編輯 –

+0

只要性能可行,你發佈的程序大約快50ms,並在1250ms而不是1300響應。這不是那麼有意義...... :-(但我只需要更少的電話...... –