我最近在阅读Rails中
:joins
和
:includes
之间的区别。以下是我理解的解释(附有示例):
考虑以下情况:
用户(User)有多条评论(Comment),每条评论属于一个用户。
用户(User)模型具有以下属性: 姓名(Name)(字符串), 年龄(Age)(整数)。评论(Comment)模型具有以下属性:内容(Content), 用户ID(user_id). 评论可以没有用户ID。
Joins:
:joins
在两个表之间执行内连接(inner join)操作。因此,
Comment.joins(:user)
#<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
#<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">]>
将获取所有用户ID等于comments表中的user_id(users表)的记录。因此,如果您执行
Comment.joins(:user).where("comments.user_id is null")
你将会得到一个空数组,如下所示。
此外,联结不会将关联的表加载到内存中。因此,如果执行以下操作:
comment_1 = Comment.joins(:user).first
comment_1.user.age
#=> User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
#=> 24
正如您所看到的,comment_1.user.age
会在后台再次发出数据库查询以获取结果。
includes:
:includes
在两个表之间执行 左外连接。因此,
Comment.includes(:user)
#<Comment id: 2, content: "Hi I am Ankita.This is my first comment!", user_id: 2, created_at: "2014-11-12 18:29:29", updated_at: "2014-11-12 18:29:29">,
#<Comment id: 3, content: "Hi I am John.This is my first comment!", user_id: 3, created_at: "2014-11-12 18:30:25", updated_at: "2014-11-12 18:30:25">,
#<Comment id: 4, content: "Hi This is an anonymous comment!", user_id: nil, created_at: "2014-11-12 18:31:02", updated_at: "2014-11-12 18:31:02">]>
这将导致一个包含来自评论表的所有记录的联接表。 因此,如果您执行
Comment.includes(:user).where("comment.user_id is null")
它将获取评论用户ID为空的记录,如所示。
此外,includes会将两个表加载到内存中。因此,如果您执行以下操作
comment_1 = Comment.includes(:user).first
comment_1.user.age
正如你所注意到的,comment_1.user.age只是从内存中加载结果,而不会在后台触发数据库查询。
includes
(对于任何阅读此内容的人)。 - onebree:preload
和:eager_load
:https://www.bigbinary.com/blog/preload-vs-eager-load-vs-joins-vs-includes - Dave Powers