Laravel 关系查询优化

Posted

技术标签:

【中文标题】Laravel 关系查询优化【英文标题】:Laravel relationship query optimization 【发布时间】:2016-12-08 12:17:12 【问题描述】:

首先我为标题道歉,我找不到更好的东西。

在我的项目中,我有用户和组。用户可以加入群组并创建群组。关系定义如下。

用户模型

/** Get all the groups the user is administrator of
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function groupsAdmin()

    return $this->hasMany('App\Group','group_admin_id','id');

组模型

/** Get the users in a group
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function users()

    return $this->belongsToMany(\App\User::class,'groups_users', 'group_id','user_id');

我要做的是获取所有加入用户创建的组的用户。为此,我在我的用户模型中编写了一个方法:

/**
 * Returns all the users who have attended groups created by this user
 */
public function getPastGroupAttendees()

    // first verify if the user is admin of any group
    if(!$this->groupsAdmin)
    
        return false;
    

    $attendees = array();

    foreach($this->groupsAdmin as $group)
    
        if(count($group->users) > 0) $attendees[] = $group->users;
    
    return $attendees;


但是这种方法的问题是它的速度很慢,并且会随着新数据而变慢。而且由于用户可以加入多个组,我会从这种方法中获得重复的用户。 因此,如果有人可以向我展示一些优化和纠正此问题的方向,那将非常有帮助。

【问题讨论】:

【参考方案1】:

您可以在User 模型中设置两个关系:

public function groupsAdmin()

    return $this->hasMany('App\Group', 'group_admin_id', 'id');


public function groups()

    return $this->belongsToMany('App\Group');

对于管理员是一对多,对于组和用户是多对多(您需要在此处使用数据透视表)。

要加载数据,请使用eager loading:

$groupWithUsers = Group::where('group_admin_id', $adminId)->with('users')->first();
$groupsOfUsers = User::with('groups')->get();

要删除重复项,您可以遍历组和 merge() 所有用户集合为一个,然后使用 unique() 方法删除重复项。

另一种方法是为数据透视表创建模型,并使用简单易读的代码获取组的所有用户:

$groups = Group::where('group_admin_id', $adminId)->pluck('id'); // Get IDs of groups.
UserGroup::whereIn('group_id', $groups)->get()->unique(); // Get unique users from these groups.

【讨论】:

谢谢,这样加载时间变快了,但仍然存在重复用户问题。例如,一个用户加入了我创建的两个组。所以我会为两组获得该用户两次。我可以遍历记录并删除列出两次的任何用户,但这会有效吗?? 非常感谢。我选择了您的第一个解决方案 merge()unique()

以上是关于Laravel 关系查询优化的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 使用大数据优化更新/插入查询的最佳方法是啥?

Laravel 搜索查询优化

第九章 关系查询处理和查询优化——关系数据库系统的查询处理

优化 Laravel Eloquent whereHas() 查询 - 非常慢

数据库 chapter 9 关系查询处理和查询优化

Laravel - 如何优化 MIN - MAX - orderBy 查询?