我有一个book id数组,我需要迭代每个并在Hash(@book_comments)中保存每个注释的数量,这些注释将book_id作为键,并将该书的注释数作为值。书中有很多评论,评论属于书籍。
@book_ids.map {|id| @book_comments[id] = Book.find(id).comments.size}
这将使用这两个查询命中数据库,查看我在数组上的ID数量。
SELECT `books`.* FROM `books` WHERE `books`.`id` = ? LIMIT 1
SELECT COUNT(*) FROM `comments` WHERE `comments`.`book_id` = ?
当然有更好的方法。 如果你知道,请教我。 谢谢。
答案 0 :(得分:5)
这应该得到你的哈希:
@book_comments = Comment.where(book_id: @book_ids).group(:book_id).count
答案 1 :(得分:3)
使用此代码:
comment_counts_by_book = Book.select('books.id, count(comments.id) as comments_count').
joins('left outer join comments on comments.book_id = books.id').
group('books.id').inject({}) { |h, book| h[book.id] = book.comments_count; h }
comment_counts_by_book
# => {1=>2, 2=>5, ...}
它执行单个数据库查询,返回仅填充Book
和:id
属性的:comments_count
个对象。然后使用inject
将结果转换为带有book id的哈希作为键,并将注释计为值。
答案 2 :(得分:1)
如果您正在使用Rails 4,您也可以执行以下操作:
Comment.eager_load(:book).group(:book).count
它会生成如下内容:
=> #{1=>2, 2=>4, 3=>9}
答案 3 :(得分:0)
这对你有用吗?我不确定我是否正确理解了这个问题。让我知道。
Book.find(@book_ids).map(&:comments).size
这更接近你想要的吗?
@book_ids.map do |id|
{
id => Book.find(id).map(&:comments).size
}
end
{}.tap do |hash|
@book_ids.each do |book_id|
hash[book_id] = Book.find(book_id).map(&:comments).size
end
end
答案 4 :(得分:0)
您应该使用includes来急切加载注释,然后迭代该查询。
books = Book.where(id: @book_ids).includes(:comments)
books.each do |book|
@book_comments[book.id] = book.comments.length
end