我已经使用Laravel构建了一个应用程序,最终我拥有了很深的嵌套关系,有时我需要查询它们。数据库是MySQL。
例如,我想检索所有允许阅读书的用户。我的数据结构如下:
浏览后,我发现有人建议采用以下方式解决嵌套关系:
onCreate
我喜欢代码很有意义,但性能却很糟糕。.super
我重新编写了如下函数:
// class Book extends Model
public function readers() {
$bookId= $this->id;
return User::whereHas('memberships', function($m) use($bookId) {
$m->whereHas('group', function($g) use($bookId) {
$g->whereHas('rights', function($r) use($bookId) {
$r->where('resource_id', $bookId)->where('action', 'read');
});
});
});
}
使用此代码,我平均执行时间为 4ms ,这显然要好得多。但是,在编写嵌套请求方面,这看起来也不太“方法”。
我真的很想了解:
答案 0 :(得分:1)
首先,在不知道为什么会发生的情况下提高性能的好方法:)
您的readers()->get()
函数在层次结构中上下移动,这就是为什么它更有意义但更慢的原因。它与运行3个foreach嵌套循环相同,它首先返回具有成员身份的所有用户,然后为每个用户进行迭代,找到其所属的所有组,然后迭代每个组并找到每个组的权限,然后迭代每个权限并获取通过匹配resource_id和action所需的条目。
您的readersNew()->get()
在层次结构中向下遍历,这就是为什么它更快的原因。它首先根据匹配的权限提取目标组,然后提取与该组关联的用户身份,从而更快。
readersNew()->get()
是最好的方法,如果您愿意,您可以更改写作习惯以使其更有意义:
public function readersNew() {
$bookId= $this->id;
$targetGroup = Right::where(['resource_id' => $bookId, 'action' => 'read'])->pluck('group_id');
$associatedUserIds = UserMembership::whereIn('group_id', $g)->pluck('user_id');
return User::whereIn('id', $associatedUserIds);
}
我希望对您有帮助