我有以下型号:
月亮 – >行星 – >明星 – > galaxy – >宇宙
Moon belongs_to Planet,Planet belongs_to Star等等:
class Moon < ActiveRecord::Base belongs_to :planet,inverse_of: :moons has_one :star,through: :planet has_one :galaxy,through: :star has_one :universe,through: :galaxy end
class Planet < ActiveRecord::Base belongs_to :star,inverse_of: :planets has_many :moons,inverse_of: :planet,dependent: :destroy end
问题
我试图让Rails将这些对象的层次结构加载到内存中.我正在努力实现两件事:
>使用一个有效的查询加载一切
>能够使用诸如moon.galaxy之类的调用而不是moon.planet.star.galaxy之类的调用而无需额外调用数据库.
我尝试了两种方法.第一个(m1)呼叫包含在月亮上,所有关系变平.这导致查询效率非常低,但我可以调用m1.galaxy.第二个(m2)调用包括关系层次.这会产生有效的查询,但我可以调用m2.galaxy而无需访问数据库.
这样做的正确方法是什么?
例
irb(main):152:0* m1 = Moon.includes(:planet,:star,:galaxy).where(galaxies: {name: 'The Milky Way'}).first sql (1.9ms) SELECT "moons"."id" AS t0_r0,"moons"."name" AS t0_r1,"moons"."planet_id" AS t0_r2,"moons"."created_at" AS t0_r3,"moons"."updated_at" AS t0_r4,"planets"."id" AS t1_r0,"planets"."name" AS t1_r1,"planets"."star_id" AS t1_r2,"planets"."created_at" AS t1_r3,"planets"."updated_at" AS t1_r4,"stars"."id" AS t2_r0,"stars"."name" AS t2_r1,"stars"."galaxy_id" AS t2_r2,"stars"."created_at" AS t2_r3,"stars"."updated_at" AS t2_r4,"galaxies"."id" AS t3_r0,"galaxies"."name" AS t3_r1,"galaxies"."universe_id" AS t3_r2,"galaxies"."created_at" AS t3_r3,"galaxies"."updated_at" AS t3_r4 FROM "moons" LEFT OUTER JOIN "planets" ON "planets"."id" = "moons"."planet_id" LEFT OUTER JOIN "planets" "planets_moons_join" ON "planets_moons_join"."id" = "moons"."planet_id" LEFT OUTER JOIN "stars" ON "stars"."id" = "planets_moons_join"."star_id" LEFT OUTER JOIN "planets" "planets_moons_join_2" ON "planets_moons_join_2"."id" = "moons"."planet_id" LEFT OUTER JOIN "stars" "stars_moons_join" ON "stars_moons_join"."id" = "planets_moons_join_2"."star_id" LEFT OUTER JOIN "galaxies" ON "galaxies"."id" = "stars_moons_join"."galaxy_id" WHERE "galaxies"."name" = $1 ORDER BY "moons"."id" ASC LIMIT 1 [["name","The Milky Way"]] => #<Moon id: 1,name: "The Moon",planet_id: 1,created_at: "2015-10-28 10:02:04",updated_at: "2015-10-28 10:02:04"> irb(main):153:0> m2 = Moon.includes(planet: {star: :galaxy}).where(galaxies: {name: 'The Milky Way'}).first sql (0.5ms) SELECT "moons"."id" AS t0_r0,"galaxies"."updated_at" AS t3_r4 FROM "moons" LEFT OUTER JOIN "planets" ON "planets"."id" = "moons"."planet_id" LEFT OUTER JOIN "stars" ON "stars"."id" = "planets"."star_id" LEFT OUTER JOIN "galaxies" ON "galaxies"."id" = "stars"."galaxy_id" WHERE "galaxies"."name" = $1 ORDER BY "moons"."id" ASC LIMIT 1 [["name",updated_at: "2015-10-28 10:02:04">
m1 – 我可以在内存中调用moon.galaxy.name,m2 – moon.galaxy.name调用DB
irb(main):154:0> m1.galaxy.name => "The Milky Way" irb(main):155:0> m2.galaxy.name galaxy Load (0.5ms) SELECT "galaxies".* FROM "galaxies" INNER JOIN "stars" ON "galaxies"."id" = "stars"."galaxy_id" INNER JOIN "planets" ON "stars"."id" = "planets"."star_id" WHERE "planets"."id" = $1 LIMIT 1 [["id",1]] => "The Milky Way"
m1 – moon.planet.star.galaxy.name调用DB,m2 – 我可以在内存中调用moon.planet.star.galaxy.name
irb(main):156:0> m1.planet.star.galaxy.name Star Load (3.3ms) SELECT "stars".* FROM "stars" WHERE "stars"."id" = $1 LIMIT 1 [["id",1]] galaxy Load (0.3ms) SELECT "galaxies".* FROM "galaxies" WHERE "galaxies"."id" = $1 LIMIT 1 [["id",1]] => "The Milky Way" irb(main):157:0> m2.planet.star.galaxy.name => "The Milky Way"
查询的差异
解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。