按关联计数订购产品

时间:2009-11-19 01:46:34

标签: ruby-on-rails ruby activerecord

类产品

has_many :sales

end

Class Sale

belongs_to :product

end

我如何获得最畅销的产品..(产品找到所有..订购.. ventas ..)?

3 个答案:

答案 0 :(得分:15)

您可能希望通过在产品模型中使用计数器缓存列,一举两得(另一只鸟正在表演)。例如,假设您为产品X进行销售。当该销售提交到数据库时,它将运行回调以增加该产品在数据库中产品行中的销售数量。当你销毁时,反过来会减少产品的数量。

您需要在products表中设置缓存列。在新迁移中,请执行以下操作:

add_column :products, :sales_count, :integer, default => 0

Product.reset_column_information

Product.all.each do |product|
  Product.update_counters(product.id, :sales_count => product.sales.length
end

您还需要对产品和销售模型进行一些更改,例如:

class Product < ActiveRecord::Base
  has_many :sales
end

class Sale < ActiveRecord::Base
  belongs_to :product, :counter_cache => true
end

然后,您不必加载所有销售协会(在大型应用程序中,这将是危险的),您只需加载产品,并且您在行中拥有相关销售数量,只是性能成本的一小部分。

希望这有帮助!

答案 1 :(得分:5)

如果您尝试按照与其相关的销售数量来订购产品,则实际上这可能是一个难题,具体取决于您的数据库。谷歌搜索从transientink.com挖出答案,但这个解决方案对我个人不起作用。我怀疑这是因为与MySQL相比,PostgreSQL处理GROUP BY子句的方式不同。

另一种选择是在Sales中的产品关联上启用counter_cache(请参阅详细信息的链接),然后按计数器缓存字段排序。

另一个选择是使用Ruby进行排序:

@top_products = Product.find(:all, :include => :sales).sort_by { |p| p.sales.size }

这有两个主要问题,第一个是你利用你的网络服务器进行排序,这会减慢请求(可能会显着,取决于产品的数量。)其次,你不能做在finder中使用:limit选项,所以如果你只想要销售最多的十大产品,你必须从数据库中取出所有产品,在应用程序中对它们进行排序,然后再限制它们。

答案 2 :(得分:3)

检索产品时,您可以执行以下操作:

 @products = Product.find(:all, :include => :sales, :order => "sales.value DESC")

'sales.value'可以替换为您尝试订购的任何值...


编辑:忽略我的其余答案。它不会按销售价值按降序返回Product对象,它将按销售价值的降序返回与产品关联的Sales对象。 :P

此外,您可以在模型中指定顺序,如:

    Class Product
        has_many :sales, :order => 'sale_value DESC'
    end

其中'sale_value'是您尝试订购的任何内容......并且这样做,检索产品,您可以这样做:

 @products = Product.all