如何计算最流行的订单行组合? (或任何类似的订单/订单行数据库安排)

发布于 2024-11-05 23:16:10 字数 327 浏览 3 评论 0原文

我正在使用 Ruby on Rails。我有几个适合正常订单/订单行安排的模型,即

class Order
  has_many :order_lines
end

class OrderLines
  belongs_to :order
  belongs_to :product
end

class Product
  has_many :order_lines
end

(从我的真实模型大大简化!)

通过订单行计算出最受欢迎的单个产品相当简单,但是我可以使用什么神奇的 ruby​​-fu计算最受欢迎的订购产品组合。

干杯, 格雷姆

I'm using Ruby on Rails. I have a couple of models which fit the normal order/order lines arrangement, i.e.

class Order
  has_many :order_lines
end

class OrderLines
  belongs_to :order
  belongs_to :product
end

class Product
  has_many :order_lines
end

(greatly simplified from my real model!)

It's fairly straightforward to work out the most popular individual products via order line, but what magical ruby-fu could I use to calculate the most popular combination(s) of products ordered.

Cheers,
Graeme

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷月断魂刀 2024-11-12 23:16:10

我的建议是为每个订单创建一个由 Product.id 数字组成的数组 a,然后执行相当于

h = Hash.new(0)
# for each a
  h[a.sort.hash] += 1

您自然需要考虑运营规模以及数量的操作您愿意估算结果。

外部解决方案

创建一个“组合”模型并通过哈希索引表,然后每个订单都可以增加一个计数器字段。另一个字段将准确记录该哈希值所指的组合。

内存解决方案

查看最近 100 个订单,并在需要时重新计算内存中的订单流行度。 Hash#sort 将为您提供流行度哈希值的排序列表。您可以创建一个复合对象来记住正在计算的顺序组合,或者只是扫描原始数据以查找哈希值。

My suggestion is to create an array a of Product.id numbers for each order and then do the equivalent of

h = Hash.new(0)
# for each a
  h[a.sort.hash] += 1

You will naturally need to consider the scale of your operation and how much you are willing to approximate the results.

External Solution

Create a "Combination" model and index the table by the hash, then each order could increment a counter field. Another field would record exactly which combination that hash value referred to.

In-memory Solution

Look at the last 100 orders and recompute the order popularity in memory when you need it. Hash#sort will give you a sorted list of popularity hashes. You could either make a composite object that remembered what order combination was being counted, or just scan the original data looking for the hash value.

趁微风不噪 2024-11-12 23:16:10

感谢数字罗斯的提示。我遵循外部解决方案的想法并执行了以下操作。它与建议略有不同,因为它保留单个 order_combos 的记录,而不是存储计数器,因此也可以按日期查询,例如上周最受欢迎的前 10 个订单。

我在订单中创建了一个方法,它将订单项列表转换为逗号分隔的字符串。

def to_s
  order_lines.sort.map { |ol| ol.id }.join(",")
end

然后我添加了一个过滤器,以便每次下订单时都会创建组合。

after_save :create_order_combo

def create_order_combo
  oc = OrderCombo.create(:user => user, :combo => self.to_s)
end

最后我的 OrderCombo 类如下所示。我还提供了该方法的缓存版本。

class OrderCombo

  belongs_to :user

  scope :by_user, lambda{ |user| where(:user_id => user.id) }

  def self.top_n_orders_by_user(user,count=10)
    OrderCombo.by_user(user).count(:group => :combo).sort { |a,b| a[1] <=> b[1] }.reverse[0..count-1]
  end

  def self.cached_top_orders_by_user(user,count=10)
    Rails.cache.fetch("order_combo_#{user.id.to_s}_#{count.to_s}", :expiry => 10.minutes) { OrderCombo.top_n_orders_by_user(user, count) }
  end
end

它并不完美,因为它没有考虑到当有人在订单中订购更多一件商品时受欢迎程度的增加。

Thanks for the tip digitalross. I followed the external solution idea and did the following. It varies slightly from the suggestion as it keeps a record of individual order_combos, rather than storing a counter so it's possible to query by date as well e.g. most popular top 10 orders in the last week.

I created a method in my order which converts the list of order items to a comma separated string.

def to_s
  order_lines.sort.map { |ol| ol.id }.join(",")
end

I then added a filter so the combo is created every time an order is placed.

after_save :create_order_combo

def create_order_combo
  oc = OrderCombo.create(:user => user, :combo => self.to_s)
end

And finally my OrderCombo class looks something like below. I've also included a cached version of the method.

class OrderCombo

  belongs_to :user

  scope :by_user, lambda{ |user| where(:user_id => user.id) }

  def self.top_n_orders_by_user(user,count=10)
    OrderCombo.by_user(user).count(:group => :combo).sort { |a,b| a[1] <=> b[1] }.reverse[0..count-1]
  end

  def self.cached_top_orders_by_user(user,count=10)
    Rails.cache.fetch("order_combo_#{user.id.to_s}_#{count.to_s}", :expiry => 10.minutes) { OrderCombo.top_n_orders_by_user(user, count) }
  end
end

It's not perfect as it doesn't take into account increased popularity when someone orders more of one item in an order.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文