【问题标题】:Laravel model: complex query from external database?Laravel 模型:来自外部数据库的复杂查询?
【发布时间】:2018-07-14 15:57:44
【问题描述】:

Laravel 新手,请善待。 :-)

我有一个外部只读遗留数据库。 我使用复杂查询从 Products 表中检索“top products”。 这是一个昂贵的查询,应该被缓存(如果需要,每天只更新一次)。查询的参数:自日期 xyz 以来的热门产品,最大结果数(默认值:500)。

数据库是完全只读的。无法创建视图(即solution to a similar question)。

我希望能够将这些顶级产品视为 Laravel 中的常规模型。 这样我就可以应用关系/过滤器。例如。检查购买模型以购买“顶级产品”,获取具有供应商价值“xyz”的“顶级产品”。

最好的方法是什么?

【问题讨论】:

  • 此查询是否在存储过程中?或者你打算用 Eloquent 重写它?
  • 它是一个复杂的常规查询(不是存储过程),带有一些 FROM 和 JOIN 的子 SELECT。我打算将其视为原始 T-SQL。
  • 我会尽可能地考虑用 Eloquent 重写。有 whereRaw()selectRaw() 方法,因此即使您有时不得不使用原始 SQL,您仍然可以获得 ORM 的好处。

标签: sql laravel laravel-5 eloquent


【解决方案1】:

运行这样的查询最有效的方法通常是在存储过程中运行它。您可以在迁移中定义存储过程,以确保它在数据库中定义并使用以下内容运行它:

DB::select('exec my_stored_procedure(?,?)', [$a, $b]);

但是,据我了解,这在 Eloquent 中效果不佳(我以前没有机会尝试过这种方法)。您可以通过将响应包装在 collect() 中将其转换为集合,这可能会有所帮助,但这意味着在 PHP 中进行排序和过滤,其性能总是比在 SQL 中低。

或者,您可以使用 Eloquent 重写整个内容,并使其成为模型上的方法。

如果您需要在 SQL 中进一步细化此查询,这样做的方法是在约束查询的模型上定义 local scope,如下例所示:

public function scopeTopProducts($query)
{
    return $query->where('a', true);
}

然后您可以调用MyModel::topProducts()->find(1),知道范围将限制查询集是安全的。

可以使用Laravel's caching system 缓存响应。但是,对于后一种方法,您不能缓存范围,只能缓存最终查询的结果。如果这可能会导致问题,您最好只使用可以缓存的单个查询填充初始数据并使用Laravel's collections 来进一步过滤数据而不是 SQL。

【讨论】:

  • 谢谢马特。看来我需要学习更多才能继续!我认为迁移不适用。遗留数据库是完全只读的,我的应用程序无法进行任何修改。缓存最终查询的结果很好(实际上:想要)。我想我得把它停好,直到我的知识有所提高。
  • @wivku 使用 Laravel 的集合,你可以获得相当好的过滤。如果你在 Eloquent 中使用 with() 方法预先加载任何你需要的关系,那么这些关系将与结果一起被拉入。然后,您可以使用 Laravel 集合中的方法(也混合到 Eloquent 响应中)对结果进行排序和过滤。如果您无法以这种方式获得所需的东西,我会感到非常惊讶。
  • @wivku 这么说吧,Laravel 集合包括 map 和 reduce 操作,使用它们可以对数据执行一些极其复杂的操作。如果您想缓存响应,然后继续对可能是您最好的选择的数据进行操作。
猜你喜欢
  • 2017-06-16
  • 2016-08-13
  • 2020-03-29
  • 2017-05-10
  • 2015-01-05
  • 2014-06-16
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多