当我必须加入另一张桌子时,真的一直在努力让一群人上班。我可以在没有加入时让小组上班,但是当我想在另一张桌子上按专栏分组时,我开始遇到问题。
Tables:
Book
id, category_id
Category
id, name
ActiveRecord schema:
class Category < ActiveRecord::Base
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :category
end
我正试图按类别计算得到一个小组。 I.E.我想知道每个类别中有多少本书。
我尝试了很多东西,这是最新的,
books = Book.joins(:category).where(:select => 'count(books.id), Category.name', :group => 'Category.name')
我希望得到像
这样的东西[{:name => fiction, :count => 12}, {:name => non-fiction, :count => 4}]
有什么想法吗?
提前致谢!
答案 0 :(得分:1)
如果您只是在每个类别中的书籍数量之后,您从has_many
关联获得的关联方法可能就足够了(请查看Association Basics guide)。您可以使用
@category.books.size
如果你想构建你描述的数组,你可以用以下内容自己构建它:
array = Categories.all.map { |cat| { name: cat.name, count: cat.books.size } }
作为额外的一点,如果您经常查看某个类别中的图书数量,您可能还需要考虑使用计数器缓存,因此获取某个类别中的图书数量并不需要额外的数据库之旅。为此,您需要在图书模型中进行以下更改:
# books.rb
belongs_to :category, counter_cache: true
创建一个迁移来添加和初始化计数器缓存使用的列:
class AddBooksCountToCategories < ActiveRecord::Migration
def change
add_column :categories, :books_count, :integer, default: 0, null: false
Category.all.each do |cat|
Category.reset_counters(cat.id, :books)
end
end
end
编辑:经过一些实验,以下内容应该可以满足您的需求:
counts = Category.joins(:books).count(group: 'categories.name')
这将返回一个散列,其中类别名称为键,计数为值。您可以使用.map { |k, v| { name: k, count: v } }
将其设置为您在问题中指定的格式。
我会密切注意这样的事情 - 一旦你拥有足够多的书籍,加入可能会使事情变得缓慢。使用counter_cache
将始终是最高效的,并且对于足够多的书籍,急切加载两个单独的查询也可以提供更好的性能(这是使用includes
的急切加载从使用更改的原因加入Rails 2.1中的多个查询。
答案 1 :(得分:0)
这个怎么样:
Category.joins(:books).group("categories.id").count
它应返回一组键/值对,其中键表示类别ID,值表示与该类别关联的书籍数。