我有3张桌子:biographies, affiliations, communities
从属关系属于传记和社区,即从属关系具有传记ID和社区ID作为外键,所有关系都具有has_one关系。传记通过隶属关系与社区联系起来
在Rails控制台中,当我执行以下操作:
b = Biography.joins(:affiliation => :community)
然后,这是sql输出:
Biography Load (0.2ms) SELECT "biographies".* FROM "biographies" INNER JOIN "affiliations" ON "affiliations"."biography_id" = "biographies"."id" INNER JOIN "communities" ON "communities"."id" = "affiliations"."community_id" LIMIT ? [["LIMIT", 11]]
到目前为止,在相同的控制台会话中继续进行,然后执行:
b.first.affiliation
然后,输出为:
D, [2019-04-06T23:21:20.417201 #38967] DEBUG -- : Biography Load (0.3ms) SELECT "biographies".* FROM "biographies" INNER JOIN "affiliations" ON "affiliations"."biography_id" = "biographies"."id" INNER JOIN "communities" ON "communities"."id" = "affiliations"."community_id" ORDER BY "biographies"."id" ASC LIMIT ? [["LIMIT", 1]]
D, [2019-04-06T23:21:20.418180 #38967] DEBUG -- : Affiliation Load (0.1ms) SELECT "affiliations".* FROM "affiliations" WHERE "affiliations"."biography_id" = ? LIMIT ? [["biography_id", 1], ["LIMIT", 1]]
首先:为什么要进行另一个联接,它不应该使用第一个activerecord查询中的联接吗?
秒:为什么还有另一个选择日志?它不应该使用联接的结果而不是新的选择吗?
在执行时继续:
b.first.affiliation.community
然后,它最终输出另一个从社区中进行选择的日志。
它实际上是在运行一个全新的查询,还是仅从第一个查询存储在内存中的结果中获取它?以及我该如何告诉真实与记忆?
谢谢。
答案 0 :(得分:1)
第一个查询中的join
是一个内部联接:它告诉ActiveRecord仅加载与社区有联系的传记。
如果要访问这些记录并避免进行N + 1查询,则可以使用附加的includes
语句或使用eager_load
。
是的:只要您看到控制台输出一条SQL语句,就意味着正在运行一个新查询。
答案 1 :(得分:0)
b = Biography.joins(:affiliation => :community)
表示获取由Biographies
组成的affiliation
的所有community
,这意味着您正在基于Biographies
加载inner join
的子集条件(父表在关联表中至少应有一个引用)。
如果要preload
整个结果,可以使用:
b = Biography.preload(:affiliation => :community)