【问题标题】:Efficient way to return select columns from Rails 4 ActiveRecord nested query从 Rails 4 ActiveRecord 嵌套查询返回选择列的有效方法
【发布时间】:2014-06-16 09:17:32
【问题描述】:

在我的 Rails 4 应用程序中,我有以下模型:

class Person < ActiveRecord::Base
    has_many :addresses
  end

class Address < ActiveRecord::Base
  belongs_to :person
  belongs_to :city
end

class City < ActiveRecord::Base
  has_many :addresses
end

我正在使用:includes 函数将查询结果返回到一个变量中:

Address.includes(:person, :city).where("person_id = 1")

它按预期工作,只是我不希望查询返回每一列。

这是我尝试过的:

  • 使用select 并明确指定表名和列名,例如“city.name”,但 Rails 会生成一个带有外连接的大查询,这可能会非常昂贵,尤其是当有大量并发请求时,因此更喜欢更好的解决方案。
  • 不想硬编码完整和原始的 SQL 语句,因为以后会出现维护问题
  • 创建一个新的“虚拟”belongs_to 关系,如地址:belongs_to :city_select_columns, -&gt; { select('name') }, :class =&gt; 'City',但这不起作用(实际上我不确定是否支持 select,只遇到有关 @987654329 的文档@ 到目前为止)。
  • 可以在 City 和 Person 中定义 scope 吗?但我不确定它应该如何定义,或者这样做是否有意义

建议?谢谢

【问题讨论】:

  • 您说“它按预期工作,只是我不希望查询返回每一列。”但是您想要哪些列?

标签: sql ruby-on-rails ruby-on-rails-4 scope rails-activerecord


【解决方案1】:

你试过了吗?

class Person < ActiveRecord::Base
    has_many :addresses
    has_many :cities, :through => :addresses
end

class Address < ActiveRecord::Base
  belongs_to :person
  belongs_to :city
end

class City < ActiveRecord::Base
  has_many :addresses
end

然后:

Person.find(1).cities.pluck(:name)

看起来这会生成一个INNER JOIN,但使用索引应该不会太昂贵?

【讨论】:

  • 无法正确返回多个列。我最终使用了原始连接 SQL。试图利用 API,但猜测有时蛮力会更有效:/
  • 我刚刚尝试了...pluck(:x,:y),它返回了数组数组:[[x1,y1],[x2,y2]]... 这还不够吗?
【解决方案2】:

你试过select吗?

Address.select(<output_columns>).includes(:person, :city).where("person_id = 1")

【讨论】:

  • 这就是我使用联接的意思,刚刚更新了我的问题。使用.select('city.name, etc.'),Rails 会在后端生成一个涉及外部连接的大查询,我不喜欢使用它:/
  • 在我的例子中,使用:includes 生成了 3 个查询,没有连接
【解决方案3】:

使用 Rails 的 API 找不到好的查询方法,我最终编写了一个原始的内部连接 ​​SQL,然后调用 ActiveRecord::Base.connection.execute 来运行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多