如果我有这个型号
class Post extends Model{
public function author()
{
return $this->belongsTo(Author ::class);
}
public function category()
{
return $this->belongsTo(Category ::class);
}
}
class Author extends Model{
}
class Category extends Model{
}
并运行此
$posts = Post::with('author', 'category')->get()
laravel运行3个MySQL查询。对我来说,速度和性能在这里并不是真正的问题(虽然,它可能适用于某人),问题是如果我想按作者姓名或类别名称对帖子进行排序,我无论如何需要手动加入帖子和类别,这是非常尴尬。
1.第一个问题是我需要担心选择
->select('posts.*')
e.g。可以选择类别中的id并将其水合成Post模型。
2.第二个问题是我需要担心groupBy - > GROUPBY(' posts.id&#39); 例如如果关系是hasOne并且帖子有多个类别,则查询将返回更多类别的行。
3.第三个问题是我需要改变所有其他的东西
->where('date', $date)
到
->where('posts.date', $date)
因为帖子和类别可以有日期属性而没有"模糊列"错误可以抛出。
我认为以雄辩的方式运行联接可能非常尴尬且容易出错。有没有人有使用其他框架ORM(它不一定是PHP)的经验,它们使用join进行预先加载和连接以对相关表进行排序?
PS。对于过滤相关表我不需要使用连接但whereHas使子查询通常比连接慢。
答案 0 :(得分:1)
我很长一段时间都在使用Laravel / Eloquent这个问题,并且分组,顺序和性能都是同一设计问题的一部分:Eloquent用于模型而不用于查询。
但是,另一方面,它是一种富有表现力的语言,可以完成任务,使用DB :: table(' ....') - >加入将是一种浪费。 ..或任何类似的东西。
我最满意的解决方案是使用非规范化视图模式。
规范化数据是有效存储的数据,在创建专门视图(例如具有列子集的简明列表,特定顺序或分组)时难以查询。
另一方面,非规范化数据是仅在应用程序的单个部分中有意义的数据,但它的格式和顺序正确。
这种分离很重要,因为我们忽略了在数据库中保存两者是多么容易。我们只需要决定一致我们的非规范化视图和规范化数据是多少。
总而言之,让我们举一个例子:艺术家,专辑,歌曲 - 所有读者都应该清楚地了解这些关系。
我有一个页面,其中显示每个艺术家第一首歌曲的列表,按艺术家姓氏按字母顺序排列,以及该歌曲出现在哪张专辑中。如何以雄辩的方式解决这个问题。啊。 此外,我已经问过我的产品团队了,我们都得出的结论是,用户看到此列表的事件比向艺术家添加新专辑或将新歌添加到相册要多100倍,尤其是第一首歌,每位新艺术家都曾经发生过一次。
如果我有一张桌子,我可以运行一些简单的东西 - FirstSong :: orderBy(' artist_last_name');
我没有在查询中捣乱,而是雄辩地更新了我的first_songs视图(或临时表或实际表格,并不重要)。我插入Song更新的事件,检查这首歌是不是第一个,如果是,我去更新我的first_songs表。我甚至在一个单独的过程中使用Laravel的队列或其他任何方式执行此操作,即使这样我的插入也没有受到影响。我甚至可以每天运行一次脚本来重新计算整个表格 - 所以first_songs有可能不是今天的更新。谁在乎?
<强> TL;博士强> 考虑将您的体系结构更改为具有单独的预加入,视图特定的表,以使用其自己的模型进行此类查询,而不是强制在规范化模型上进行连接。