优化雄辩的查询

时间:2014-03-06 14:52:56

标签: laravel eloquent

我需要在一个雄辩的查询中附加自定义选择,但我发现整个事情有点难以理解。这涉及一个论坛系统,其中每个论坛对象需要知道注册了多少主题关系和注释关系。这是我到目前为止所得到的:

在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);
}

此呼叫大约需要1300毫秒才能返回3个类别的5个论坛。我怀疑这是因为它执行大约16个查询而不是一个。有没有办法在select上附加“num_topics”和“num_posts”作为属性,这样我才能执行一个查询?

修改

我基本上想要的是Eloquent在我要求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

1 个答案:

答案 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对象。

呼叫次数减少但是它在一次扫描中抓取更多信息,因此可能更快或更慢,必须进行一些测试。好消息是因为它抓住了所有东西,所以不需要额外的查询。