Rails:从多个关联模型中检索最新记录

时间:2017-10-30 15:49:26

标签: ruby-on-rails ruby postgresql

我正在寻找一种最佳且性能更佳的解决方案,以便在多个有多个关联中获取最新记录,

class ModelA < ActiveRecord::Base`
  has_many books
  has_many tables
  has_many chairs
end

到目前为止,我有以下内容,以实现对这些关联中的最后一个的检索。

[books.last, tables.last, chairs.last]
  .compact
  .sort_by(&:created_at)
  .last

这会产生多个查询,从而减慢通过控制器的响应速度。是否有更好的解决方案来实现同样的目标?

提前致谢。

2 个答案:

答案 0 :(得分:0)

SQL中的UNION可以帮到你。联盟将包括您的所有查询,您将能够轻松地对其进行排序。

SELECT id, 'Book' AS type, created_at, other_fields FROM books
UNION
SELECT id, 'Table' AS type, created_at, other_fields FROM tables
UNION
SELECT id, 'Chair' AS type, created_at, other_fields FROM chairs
ORDER BY created_at;

请注意,您可以通过不同表中的公共字段进行联合。因此,您无法选择某些字段,而这些字段在其他字段中不存在。不同实体需要字段type

答案 1 :(得分:0)

让我们说:

class Publisher
  has_many :books
end

class Book
  belongs_to :publisher
end

您可以使用DISTINCT ON获取最新的行:

Book.distinct('ON(books.publisher_id)').order(created_at: :desc)

您可以使用此限制加载的关联行数:

Publisher.includes(:books)
   .where(books: Book.distinct('ON(books.publisher_id').order(created_at: :desc))

Rails非常聪明,可以将其烘焙成单个查询。

为多个关联执行此操作完全相同:

Publisher.includes(:books, :records)
   .where(
     books: Book.distinct('ON(books.publisher_id').order(created_at: :desc),
     records:  Record.distinct('ON(record.publisher_id').order(created_at: :desc)
   )

这只会加载一本书。还有一些更高性能的选项,例如横向连接,但它们更难以集成。但是如果你经常从表中读取,那么将最新的相关记录存储在父表中是有意义的:

class Publisher
  has_many :books, after_add: :set_latest_book!
  belongs_to :latest_book

  def set_latest_book!(book)
    self.update_attribute!(:latest_book_id, book.id)
  end
end

class Book
  belongs_to :publisher
end

这使您可以通过简单的查询和高性能查询来加载/包含:

Publisher.eager_load(:latest_book)