【问题标题】:Rails ActiveRecord: Counting associations of associationsRails ActiveRecord:计算关联的关联
【发布时间】:2010-10-06 18:52:44
【问题描述】:

我正在尝试编写 ActiveRecord 查找查询,但没有成功。请帮忙!

我的项目的这个功能是一种类似于 Digg 功能的博客:每个注册用户都可以为博客帖子本身或其任何回复添加星标。

以下是相关的模型类:

  • 博文(有_many Replies)
  • 回复(属于博客帖子)
  • 加星标(这表示一个用户加星标一个 BlogPost 或 Reply 的操作;它具有 BlogPost 和 Reply 的多态接口,在内部将它们称为 :starrables,充满 :starrable_id 和 :starrable_type 字段)

所以,我要做的是在 blog_post.rb 中编写一个方法,该方法将返回 BlogPost 对象及其所有回复类的星标总数。也就是说,如果一篇博文有 10 颗星,并且它有两条回复,每条有 5 颗星,它应该返回 20。

如何在不进行大量数据库事务的情况下编写此查询?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    我建议用 SQL 来做。您可以通过多种方式进行操作。你在使用 MYSQL 吗?如果您想处理 2 个查询,然后将数字相加,您可以在 SQL 中执行以下操作:

    select count(starrings.id) from starrings where starrable_type='BlogPost' and starrable_id=#{blogpost.id}

    select count(starrings.id) from starrings join replies on starrings.starrable_type='Reply' and starrable_id=replies.id and replies.blog_post_id=#{blogpost.id}

    注意:我没有测试此 SQL,可能拼写错误或拼写错误。

    您可以使用“Starring.count_by_sql(your sql here)”运行 SQL 计数,然后将 2 个数字相加。您可能可以通过联合将其缩减为 1 个 SQL 语句,但我不会打扰。

    【讨论】:

      【解决方案2】:

      假设您在 BlogPost 和 Reply 上都有一个多态方法 stars,它为每个对象返回 Starring 对象(您可能没有,但对我来说应该这样做)然后在 blog_post.rb 中您可以执行:

      def total_number_of_stars
        stars.size + replies.inject(0) { |s,v| s.stars.size += v.stars.size }
      end
      

      诚然,这会在幕后进行很多查询,但这就是 Rails 的工作方式。如果它的性能不够好,您可以将 find_by_sql 与定制 SQL 一起使用。

      【讨论】:

      • 我现在基本上是这样做的,但它的扩展性非常大。假设有一种方法可以在一两个查询中执行此操作,我宁愿让数据库完成繁重的工作。不过谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多