使用约束的急切加载会产生太多查询。我怎样才能减轻这种情况?

时间:2017-08-15 23:33:04

标签: php laravel eager-loading

我有4个表在数据库和模型中相关,如下所示:

Users (hasMany(communities), hasMany(comments), hasMany(submissions))
Communities (belongsTo(user), hasMany(submissions))
Submissions (belongsTo(community), belongsTo(user), hasMany(comments))
Comments (belongsTo(user) , belongsTo(submission))

现在。如果我使用关系来获取,比如25个最新的提交,如下:

$submissions = Submission::simplePaginate(25);

在使用foreach遍历结果后,我遇到了76个查询运行。

如果我使用以下

的急切加载
$submissions = Submission::with(['user', 'community', 'comments'])->simplePaginate(25);

我遇到了4个最佳查询(我认为)。

现在,我的问题是,在社区上,我有一个名为active的数据库字段,它接受一个活动社区1,0表示非活动社区。您可能已经猜到,之前的查询会返回所有内容,包括非活动社区。

我考虑过急切加载限制,所以我使用了以下内容:

$submissions = Submission::with([
      'community' => function($query) {
        $query->active();
      }
    ]  
  )->with(['user', 'comments'])->simplePaginate(25);

这仍然可以完成4个查询,但现在我遇到了另一个问题。此方法过滤非活动社区,但仍会加载帖子,用户和评论。现在我留下了一个结果,我从不活跃的社区获得了帖子。

最后,我在阅读本社区时尝试了以下内容:

   $submissions = Submission::whereHas(
    'community', function($query) {
      $query->active();
    }  
  )->with(['user', 'comments'])->simplePaginate(20);

因此,我使用了 - > whereHas(),而不是使用 - > with()。但是,虽然这会产生正确的结果,即它只给我来自活动社区的帖子,评论和用户,但现在根据我从Laravel Debugbar获得的反馈,它在23个查询中执行此操作。

这是正常的吗?这是我通过Eloquent执行此操作的唯一方法,而无需使用连接编写自定义查询吗?我是不是吹了23个问题?

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

您的问题是active()范围正在为您检索的每个社区运行查询,在您的情况下为20.

要优化此功能,您可以在Submission模型中建立一个特定关系,您可以主动过滤活动社区。

// Submission model

public function activeCommunities (){

    return $this->hasMany(Community::class)->whereActive(true); 
}

现在您的查询如下:

$submissions = Submission::with(['user', 'comments', 'activeCommunities])  
    ->simplePaginate(25);

我认为这应该执行4个查询。

希望这会对你有所帮助。

答案 1 :(得分:0)

所以,经过一段时间的修补,我找到了一个解决方案,但我还是不确定。我发布这个以供将来参考,因为它解决了我的问题。我使用的代码如下

  $submissions = Submission::whereHas(
      'community', function($query) {
        $query->where('is_active', true);
      }
    )->with(['user', 'community'])->withCount('comments')
  ->paginate(25);

所以,我尝试使用whereHas()在实际急切加载community模型之前检查模型是否存在,如果这有意义的话?它似乎得到了我想要的结果,因为我现在执行总共4个查询来获取所有提交,以及相关信息,过滤非活动社区。