ActiveRecords Rails中的多个连接优化

时间:2013-11-19 07:00:44

标签: mysql ruby-on-rails ruby activerecord ruby-on-rails-4

有四种模式:汽车,人,国家和宗教。

class Car < ActiveRecord::Base
  belongs_to :person
  has_one :country, through: :person
  has_one :religion, through: :person

  def self.get_indian_cars_owned_by_hindus
    self.joins(:country).joins(:religion).where("countries.name=? and religions.name=?", 'India', 'Hindu').count
  end
end

class Person < ActiveRecord::Base
  belongs_to :country
  belongs_to :religion
  has_one :car
end

class Country < ActiveRecord::Base
  has_many :persons
end

class Religion < ActiveRecord::Base
  has_many :persons
end

模型中的函数get_indian_cars_owned_by_hindus可以在表格中使用某些条件。宗教。调用函数时生成的查询是:

SELECT COUNT(*) FROM `cars` INNER JOIN `persons` ON `persons`.`id` = `cars`.`person_id` INNER JOIN `countries` ON `countries`.`id` = `persons`.`country_id` INNER JOIN `persons` `persons_cars_join` ON `persons_cars_join`.`id` = `cars`.`person_id` INNER JOIN `religions` ON `religions`.`id` = `persons_cars_join`.`religion_id` WHERE (`countries`.`name` = 'India') AND (`religions`.`name` = 'Hindu');

我最初期望查询是这样的:

SELECT COUNT(*) FROM `cars` INNER JOIN `persons` ON `persons`.`id` = `cars`.`person_id` INNER JOIN `countries` ON `countries`.`id` = `persons`.`country_id` INNER JOIN `religions` ON `religions`.`id` = `persons`.`religion_id` WHERE (`countries`.`name` = 'India') AND (`religions`.`name` = 'Hindu');

这里的ActiveRecords没有优化人员和汽车表之间的额外连接。虽然我相信mysql会在最后优化它,但是在the rails way中正确编写它的方式是什么。

我显然可以在模型人员中移动方法,但这不是我正在寻找的解决方案。可能存在多个节点的情况。

编辑:将A,B,C和D的模型名称分类为汽车,人员,国家和宗教

1 个答案:

答案 0 :(得分:1)

最好的选择是将join调用更改为不使用has_many :through关系。相反,您可以将深层关系嵌套在数组中,如下所示:

def self.get_indian_cars_owned_by_hindus
  self.joins(:person => [:country, :religion]).
  where("countries.name=? and religions.name=?", 'India', 'Hindu').
  count
end