Rails activerecord计数关联数

时间:2018-03-01 08:37:40

标签: ruby-on-rails rails-activerecord

我有一个名为Impression的模型 - 它计算每张卡片的视图(也是模型)。 我正在尝试使用卡片打印一张桌子,上个月至少有10张视图。 所以我开始 -

cards = Card.joins(:impressions).where("impressions.created_at > ? AND impressions.created_at < ?", Date.today-30.days, Date.today).uniq

然后我做了 -

cards.select {|card| card.impressions.count >= 10 }

但它经历了很长时间。我想要更高效的东西。 有关计算展示次数和排序的想法吗?

我想尽可能高效地完成它 - 不用N + 1问题迭代整个数据库,因为它可能变得非常难看。

4 个答案:

答案 0 :(得分:0)

您可以使用.last()功能

试试这个

cards = Card.joins(:impressions).where("impressions.created_at BETWEEN ? AND ?", 1.month.ago.beginning_of_month , 1.month.ago.end_of_month).uniq.last(10)

答案 1 :(得分:0)

我会使用和AREL

试试这个:

cards = Card.joins(:impressions).where(impressions: {created_at: (Date.today-30.days..Date.today)}).having(Impressions.arel_table[:id].count.gteq(10)).uniq

答案 2 :(得分:0)

不知道你的关系看起来如何以及你拥有的数据量。因此,假设您的关系看起来像

<强>卡

class Card
  has_many :impressions
end

<强>展示

class Impression
  belongs_to :card
end

我的建议是尝试这样的事情:

cards_id = Card.pluck(:id)
past_one_month_impressions_arel = Impression.where("impressions.created_at > ? AND impressions.created_at < ?", Date.today-30.days, Date.today)

cards_id_having_atleast_10_views = cards_id.select do |c_id|
  arel = past_one_month_impressions_arel.where(impressions: { card_id: cid } )
  arel.count >= 10
end

cards = Card.where(id: cards_id_having_atleast_10_views)

如果您有大量数据,也可以尝试使用find_each批量迭代。

希望有所帮助。

感谢。

答案 3 :(得分:0)

您的展示次数表'created_at列是否有索引?

如果您要查询它并且没有 - 您可以通过生成迁移文件来添加它。

add_index(:impressions, :created_at)

您可以使用纯SQL为查询添加条件,如:

cards = Card.joins(:impressions).where("impressions.created_at > ? AND impressions.created_at < ?", Date.today-30.days, Date.today).group('cards.id').having('COUNT(impressions.*) >= 10')