简体   繁体   English

Ruby on Rails / ActiveRecord:我如何(优雅地)从多个表中检索数据?

[英]Ruby on Rails / ActiveRecord: How Can I (Elegantly) Retrieve Data from Multiple Tables?

It's rather trivial to retrieve data from multiple tables that are related through foreign keys using raw SQL.使用原始 SQL 从通过外键关联的多个表中检索数据相当简单。 I can do, for example:我可以这样做,例如:

SELECT title, domestic_sales
FROM movies
  JOIN boxoffice
    ON movies.id = boxoffice.movie_id;

This would give me a table with two colums: title and domestic_sales , where the data in the first column comes from the table movies and the data in the second column comes from the table boxoffice .这将给我一个包含两列的表: titledomestic_sales销售,其中第一列中的数据来自表movies ,第二列中的数据来自表boxoffice

How can I do this in Rails using Ruby code?如何使用 Ruby 代码在 Rails 中执行此操作? I can, of course, get the same result if I use raw SQL.当然,如果我使用原始 SQL,我可以获得相同的结果。 So, I could do the following:因此,我可以执行以下操作:

ActiveRecord::Base.connection.execute(<<-SQL)
SELECT title, domestic_sales
FROM movies
  JOIN boxoffice
    ON movies.id = boxoffice.movie_id;
SQL

This would give me a PG::Result object with the data I want.这会给我一个PG::Result object 和我想要的数据。 But this is super inelegant.但这是超级不雅的。 I would like to be able to get this information without using raw SQL.我希望能够在不使用原始 SQL 的情况下获取此信息。

So, this is the first thing that comes to mind is:所以,首先想到的是:

Movie.select(:name, :domestic_sales).joins(:box_office)

The problem, however, is that the aforementioned line of code returns a bunch of Movie objects.然而,问题在于上述代码行返回了一堆Movie对象。 Since the Movie class doesn't have the domestic_sales attribute, I don't get access to that information.由于Movie class 没有domestic_sales销售属性,我无法访问该信息。

The next thing I thought was to use a loop.接下来我想到的是使用循环。 So, I could do something like:所以,我可以做类似的事情:

Movie.joins(:box_office).to_a.map do |m|
    {name: m.name, rating: m.box_office.domestic_sales}
end

This gives me exactly the data I want.这给了我我想要的数据。 But it costs n + 1 SQL queries, which is not good.但是它花费 n + 1 SQL 查询,这不好。 I should be able to get this with just one query...我应该能够通过一个查询得到这个......

So: How can I retrieve the data I want without using raw SQL and without using loops that cost multiple queries?那么:如何在不使用原始 SQL 并且不使用需要多次查询的循环的情况下检索我想要的数据?

SELECT title, domestic_sales
FROM movies
  JOIN boxoffice
    ON movies.id = boxoffice.movie_id;

translated to ActiveRecord would look like this翻译成ActiveRecord看起来像这样

Movie
  .select(:title, :domestice_sales)
  .joins("boxoffice ON movies.id = boxoffice.movie_id")

When you have proper associations defined in your models you would would be able to write:当您在模型中定义了适当的关联时,您将能够编写:

Movie
  .select(:title, :domestice_sales)
  .joins(:boxoffices)

And when you do not need an instance of ActiveRecord and would be fine with a nested array, you can even write:当您不需要ActiveRecord的实例并且可以使用嵌套数组时,您甚至可以编写:

Movie
  .joins(:boxoffices)
  .pluck(:title, :domestice_sales)

Try this way.试试这个方法。

Movie.joins(:box_office).pluck(:title, :domestic_sales)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM