【问题标题】:How can I minimize the amount of queries fired?如何最大限度地减少触发的查询量?
【发布时间】:2014-04-05 20:57:29
【问题描述】:

我正在尝试在 Laravel 4.1 中创建一个标签云,标签可以属于很多帖子,帖子可以有很多标签。我正在使用数据透视表来实现这一点(post_tag)。 到目前为止,我已经想出了这个来获取标签并检查它被使用了多少次:

public static function tagCloud($tags, $max = 10) {
    foreach($tags->toArray() as $tag) {
        $count = DB::table('post_tag')
        ->where('tag_id', $tag['id'])
        ->count();
        $cloud[$tag['slug']] = $count;

    }
    sd($cloud);
}

我将Tag::all() 传递给上述函数。显然,这将在数据库上引发大量查询,这是我试图避免的。通常你会使用预先加载来解决这个问题,但是文档似乎没有提到预先加载数据透视表和聚合的任何内容。

我希望有人可以阐明如何优化当前功能,或者可以为我指出更好的替代方案的正确方向。

【问题讨论】:

  • 在默认的 Eloquent 急切加载中不能有聚合的急切加载。您必须查询标签并使用聚合连接数据透视表,在这种情况下使用 Eloquent 并非易事。当然,您可以急切地加载关系,然后简单地对每一行的关系运行 count(),因为它将计算集合,之前只有 2 个查询
  • 如果您为数据透视表创建模型并急切加载标签和帖子会发生什么?

标签: laravel laravel-4 tag-cloud


【解决方案1】:

有时很难减少它们,但 Laravel Cache 是你的朋友:

$users = DB::table('users')->remember(10)->get();

它将记住您的查询 10 分钟。

【讨论】:

    【解决方案2】:

    我相信您在tags 表中与postsmany-to-many 关系,如下所示:

    public function posts()
    {
        return $this->belongsToMany('Post');
    }
    

    所以,你可以这样做:

    $tags = Tag::with('posts')->get();
    

    然后你可以循环遍历标签以找出每个标签包含多少帖子,如下所示:

    foreach($tags as $tag) {
        $tag->posts->count();
    };
    

    所以,你可以这样写你的函数:

    public function scopeTagCloude($query) {
        $cloud = [];
        $query->with('posts')->get()->each(function($tag) use (&$cloud) {
            $cloud[$tag['slug']] = $tag->posts->count();
        });
        return $cloud;
    }
    

    你可以这样调用这个函数:

    $tagCloude = Tag::tagCloude();
    

    如果你dd($tagCloude),那么你会得到这样的东西(示例取自我的博客应用程序):

    array (size=4)
       'general' => int 4
       'special' => int 5
       'ordinary' => int 5
       'extra_ordinary' => int 2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-04
      • 2011-07-23
      • 1970-01-01
      • 2014-08-27
      • 2021-11-20
      • 2015-03-11
      • 2018-09-15
      相关资源
      最近更新 更多