我正在尝试创建一个非常复杂的查询,并且遇到了麻烦-因此,我将回到基础知识来尝试找出我所缺少的内容。我一直在阅读Rails Guides
forActive Record Associations
和Active Record Query Interface
(特别是第12节-联接),但我无法理解它们之间的关系以及为什么需要联接/包含。
关联页面说:“使用Active Record关联,我们可以通过声明性地告诉Rails两种模型之间存在联系,从而简化这些操作和其他操作。” “查询”页面的12.2节说:“使用Active Record,您可以使用模型上定义的关联的名称作为快捷方式,以便在使用joins方法时为这些关联指定JOIN子句。”
这两个陈述在我看来似乎有些矛盾。如果我创建为belongs_to关联,为什么在尝试从两个表中提取数据时都需要联接?换一种方式来看:
class Customer < ActiveRecord::Base
has_many :orders
end
class Order < ActiveRecord::Base
belongs_to :customer
end
如果可以的话,@orders = Order.all
我可以通过这样做来输出客户名称@orders.first.customer.name
。但是,如果我想选择名称中带有“史密斯”的所有订单,我会做类似的事情@orders=Order.where('customer.name ilike "%smith%"').joins(:customer)
这种“关系”在上半年如何运作,但是在下半年需要加入呢?
您不需要加入,但是在您致电关联之前,不会加载您的数据。
这就是ActiveRecord::Base
所谓的延迟加载。
您可以在控制台的SQL输出中看到这一点。
user = User.find(1)
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
这个特定的用户模型具有遍历关系。
为什么都没有加载?
因为我们还没有打电话给他们。
user.articles
Article Load (0.3ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 1
现在我们看到查询已执行。
当使用普通的旧Ruby时,这依次成为一个问题。
例如,考虑以下内容:
users.each do |user|
puts user.articles.first.title
end
运行以下代码是有问题的,因为Ruby每次对用户进行迭代时,它仅针对该用户调用文章。
您最终要重复查询执行以下SQL的每个用户:
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 1 LIMIT 1
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 2 LIMIT 1
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 3 LIMIT 1
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 4 LIMIT 1
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 5 LIMIT 1
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` = 6 LIMIT 1
etc.
我们可以通过在单个查询中最初加载所有数据来解决此问题。
users.joins(:articles).each do |user|
puts user.articles.first.title
end
在枚举开始之前,它将执行以下SQL:
Article Load (0.5ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`user_id` IN(1, 2, 3, 4, 5, 6, etc.)
这是ActiveRecord::Base
喜欢includes
和joins
起作用的方法的地方。
这是关于此事的两篇好文章:
http://blog.arkency.com/2013/12/rails4-preloading/
https://rubyinrails.com/2014/01/08/what-is-lazy-loading-in-rails/
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句