gpt4 book ai didi

ruby-on-rails - rails : how to query the length of a has_many relationship while caching it?

转载 作者:太空宇宙 更新时间:2023-11-03 18:05:35 24 4
gpt4 key购买 nike

给定以下模型:

class Author < ApplicationRecord
has_many :books
end

如果我跑

author.books.any?

我用 EXISTS 查询访问了数据库。如果我跑

1000.times { author.books.any? }

结果是 1000 次查询,因为结果没有缓存在 author 对象的内存中。

我处于与上述类似的现实生活中,我正在调用(使用的方法)author.books.any? 数千次相同的 作者对象。

我想通过在 author 对象上缓存结果来避免过多的查询。最有表现力的方法是什么?我知道例如author.books.to_a.any? 会工作,但它不是语义的。 (它还缓存所有关联数据,而不仅仅是关联数据的长度,但这对我来说没问题,因为在我的情况下关联表非常小。)

ActiveRecord::Relation 上是否有内置的替代方案来替代 any?exists? 来满足我的需求?

最佳答案

这通常称为 N+1 查询问题。

如果您使用 includeseager_load 预先加载关联,它将不会创建计数或存在查询:

author = Author.includes(:books).first
author.books.any?

这是因为 any? 使用了 .size ,它足够聪明,可以告诉关联已经加载。因此它可以在集合上使用 .length 而不是查询数据库。

size, length and count in Rails

如果你经常需要一个没有加入的关联的计数,你可以在模型上定义一个计数器缓存。

class Book < ApplicationRecord
belongs_to :author, counter_cache: true
end
class Author < ApplicationRecord
has_many :books
end

如果有很多关联记录并且将它们加载到内存中会出现问题,这会很有用。

您还可以通过使用 select 和 join 来获取关联的计数:

authors = Author.select('authors.*, COUNT(books.*) AS authors.number_of_books')
.left_joins(:books)
.order('authors.number_of_books')

# just an example
authors.map { |a| [a.name, a.number_of_books] }

这会给出更准确的数字,因为计数器缓存中的值可能已过时。

关于ruby-on-rails - rails : how to query the length of a has_many relationship while caching it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46875950/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com