我正在寻找一种最佳且性能更佳的解决方案,以便在多个有多个关联中获取最新记录,
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
这会产生多个查询,从而减慢通过控制器的响应速度。是否有更好的解决方案来实现同样的目标?
提前致谢。
答案 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)