我正在使用 AR includes
在对象 User 和 Building 之间执行 LEFT OUTER JOIN 的方法,其中 User 可能有也可能没有 Building 关联:
users = User.includes(:building).references(:buildings)
因为我正在使用 references
,任何关联的 Building 对象都将被预先加载。
我的期望是我随后能够遍历用户列表,并检查用户是否有与其关联的建筑物而不会触发额外的查询,但实际上每当我尝试访问建筑物属性时我都会看到对于没有建筑物的用户,AR 会进行另一个 SQL 调用以尝试检索该建筑物(尽管在后续尝试中它只会返回 nil)。
这些查询显然是多余的,因为关联会在初始连接期间加载,并且似乎违背了使用包含/引用进行预加载的全部目的,因为现在我看到 N 倍的查询数量等于空关联的数量。
users.each do | user |
# This will trigger a new query when building is not present:
# SELECT "buildings".* FROM "buildings" WHERE "buildings"."address" = $1 LIMIT 1 [["address", "123 my street"]]
if user.building
puts 'User has building'
else
puts 'User has no building'
end
end
用户类:
class User < ActiveRecord::Base
belongs_to :building, foreign_key: 'residence_id'
end
有没有办法在不触发额外查询的情况下检查用户建筑关联的存在?
ON RAILS 4.2.0/POSTGRES
更新:
感谢@BoraMa 整理这个 test .看起来我们在最近的 Rails 版本中有不同的行为:
输出(RAILS 4.2.0):
User 1 has building
User 2 has building
User 3 has no building
D, [2016-05-26T11:48:38.147316 #11910] DEBUG -- : Building Load (0.2ms) SELECT "buildings".* FROM "buildings" WHERE "buildings"."id" = $1 LIMIT 1 [["id", 123]]
User 4 has no building
输出(RAILS 4.2.6)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
输出(RAILS 5.0.0)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
外卖:
- 此问题仅限于“悬挂外键(即 residence_id 列不为零,但没有相应的建筑对象)” (感谢@FrederickCheung)
- 从 Rails 4.2.6 开始,该问题已得到解决
最佳答案
听起来你被 bug 咬了在 Active Record 中,这是在 rails 4.2.3 中修复的。
在列为 nil 的情况下,Active Record 已经知道它甚至不需要尝试加载关联的对象。其余案例是受此错误影响的案例
关于sql - ActiveRecord 的意外行为包括,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37400586/