我总是想知道如何查询并获得不适合模型的结果。类似于如何使用LINQ并投射到匿名对象中。
所以这是简单的架构:
# Product.rb
class Product < ActiveRecord::Base
has_many :product_views
# attributes: id, name, description, created_at, updated_at
end
# ProductView.rb
class ProductView < ActiveRecord::Base
belongs_to :product
# attributes: id, product_id, request_ip, created_at, updated_at
end
基本上我需要获得一个产品列表(最好是id和name)以及它拥有的视图数量。显然按照查看次数排序。
这是我想要的SQL:
select
p.id,
p.name,
count(pv.product_id) as views
from
product_views pv
inner join
products p on pv.product_id = p.id
group by
pv.product_id
order by
count(product_id) desc
我尝试了以下类似的东西,但是我得到了ProductView对象,我想得到一个数组或其他任何东西。
ProductView.includes(:product)
.group('product_id')
.select("products.id, products.name, count(product_id)")
使用纯SQL或LINQ这种事情是微不足道的,但我发现自己在Rails中遇到了这种查询。也许我没有想到着名的“铁路方式”,也许我错过了一些明显的东西。
那么你如何在Rails 3中进行这种查询,特别是这个?任何改善我这样做的建议都是值得欢迎的。
谢谢
答案 0 :(得分:3)
你可以使用Arel来做你想要的事情:
products = Product.arel_table
product_views = ProductView.arel_table
# expanded for readability:
sql = products.join(product_views)
.on(product_views[:product_id].eq(product[:id]))
.group(product_views[:product_id])
.order('views DESC')
.project(products[:id],
products[:name],
product_views[:id].count.as('views'))
products_with_views = Product.connection.select_all(sql.to_sql) # or select_rows to just get the values
是的,它很长,但Arel是一种非常聪明的方法来处理创建复杂的查询,无论数据库类型如何都可以重复使用。
答案 1 :(得分:2)
在Product类的类方法中:
Product.includes(:product_views).all.map { |p| [p.id, p.name, p.product_views.size] }
然后根据需要对其进行排序。
答案 2 :(得分:0)
我不知道是否有办法使用你的模型。我可能会诉诸:
Product.connection.select_rows(sql)
这将为您提供一组数组。如果您想要一组哈希值,可以使用select_all
。
答案 3 :(得分:-1)
试试这个:
@product = Product.find(#product_id)
@product_views = @product.product_views.count
(来源 - http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html#M000292)
希望这有帮助!