2014-03-06 69 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响应。这不是那么有意义...... :-(但我只需要更少的电话...... –