又是一個(gè)起源于群友(154112964 rails群 歡迎使用rails的所有人)討論的玩意
先放一些模型&關(guān)聯(lián)在前面充當(dāng)整個(gè)背景
class Author < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments
has_many :tags
has_many :guests, through: :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
has_one :guest
end
class Guest < ActiveRecord::Base
belongs_to :comment
end
class Tag < ActiveRecord::Base
belongs_to :post
end
Joins
- rails 中 joins 產(chǎn)生的均是 inner join (取交集)
- joins接收者可以是model類(lèi)本身 也可以是 ActiveRecord::Relation 的實(shí)例
belongs_to
Post.joins(:author) #返回所有 有作者的 Post INNER JOIN
SELECT "posts".* FROM "posts"
INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
has_many
author = Author.create
Author.joins(:posts)
Author.joins(:posts).where(posts: { author: author})
產(chǎn)生的sql分別如下 - 可以看出Rails在關(guān)聯(lián)上的處理還是非常機(jī)智的
SELECT "authors".* FROM "authors"
INNER JOIN "posts" ON "posts"."author_id" = "authors"."id"
SELECT "authors".* FROM "authors"
INNER JOIN "posts" ON "posts"."author_id" = "authors"."id"
WHERE "posts"."author_id" = 1
先擼到這里 。老夫去看雪了。
- joins也可以連接多個(gè)關(guān)聯(lián)
# 下面兩個(gè)操作結(jié)果等同
Post.joins(:author, :comments)
Post.joins(:author).joins(:comments)
SELECT "posts".* FROM "posts"
INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
這樣的鏈?zhǔn)讲僮?/strong>會(huì)導(dǎo)致很大的重復(fù)產(chǎn)生。inner join造成的 不介意可以u(píng)niq
嵌套連接 依舊是 鏈?zhǔn)讲僮?/strong>
# comment has_one guest
Post.joins(comments: :guest)
SELECT "posts".* FROM "posts"
INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
INNER JOIN "guests" ON "guests"."comment_id" = "comments"."id"
# 幾何級(jí)的重復(fù)
Author.joins(posts: [{ comments: :guest}, :tags])
SELECT "authors".* FROM "authors"
INNER JOIN "posts" ON "posts"."author_id" = "authors"."id"
INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
INNER JOIN "guests" ON "guests"."comment_id" = "comments"."id"
INNER JOIN "tags" ON "tags"."post_id" = "posts"."id"
includes 我單獨(dú)列出來(lái)這個(gè)吧
eager_load LEFT OUTER JOIN
has_many
ords =Order.eager_load(:line_items)
SELECT "orders"."id" AS t0_r0, "orders"."customer_id" AS t0_r1, "orders"."created_at" AS t0_r2, "orders"."updated_at" AS t0_r3,
"line_items"."id" AS t1_r0, "line_items"."order_id" AS t1_r1, "line_items"."created_at" AS t1_r2, "line_items"."updated_at" AS t1_r3
FROM "orders" LEFT OUTER JOIN "line_items" ON "line_items"."order_id" = "orders"."id"
可以看出 已經(jīng)LEFF OUTER JOIN了 line_items 下面這個(gè)遍歷是不會(huì)產(chǎn)生SQL查詢(xún)的
ords.each do |order|
order.line_items
end
o = Order.eager_load(:line_items).where("customer_id < ?", 5)
SELECT "orders"."id" AS t0_r0, "orders"."customer_id" AS t0_r1, "orders"."created_at" AS t0_r2, "orders"."updated_at" AS t0_r3,
"line_items"."id" AS t1_r0, "line_items"."order_id" AS t1_r1, "line_items"."created_at" AS t1_r2, "line_items"."updated_at" AS t1_r3
FROM "orders" LEFT OUTER JOIN "line_items" ON "line_items"."order_id" = "orders"."id" WHERE (customer_id < 5)
belongs_to
也是提前加載 和has_many 類(lèi)似 不過(guò)多陳述