【问题标题】:Including calculations on related data in an ActiveRecord query在 ActiveRecord 查询中包含相关数据的计算
【发布时间】:2010-03-01 00:02:18
【问题描述】:

假设我有一些模型:UserPostVote。一个用户有很多帖子,一个帖子有很多投票。投票可以是赞成票或反对票(存储为布尔值)。我正在考虑的是进行此类查询的最佳方式:

  1. 所有用户,以及他们获得的赞成票总数。
  2. 所有用户,以及获得最高票数的帖子。
  3. 所有用户,以及他们获得的总票数(上下)。

我认为可以通过三种方式来提高效率:

  1. 使用循环计算控制器中的投票计数。这可能会执行很多我不需要的额外查询和查询数据,例如每个帖子和每个投票记录。例如(第三个查询):

    @users = User.all
    @vote_count = @users.posts.votes.count # retrieves every post and vote, which I don't need
    
  2. 将投票计数存储为 User 模型中的字段,并在每次进行投票时使用回调来更新这些计数。这将使查询更简单,但我希望模型更松散耦合,并且每次我需要相关模型上的某种数据时都不让用户模型的架构增长。

  3. 使用某种查询,通过 SQL 执行这些类型的计算,而不是查找比我需要的更多的数据。这似乎是最好的选择,但我不知道如何处理它。有什么建议/例子吗?谢谢!

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    使用vote_fuplugin。它支持以下方法:

    user.vote_count       # all votes
    user.vote_count(true) # votes for
    user.vote_count(false) # votes against
    posts.votes_count   # all vote count
    posts.votes_for     # votes for
    posts.votes_against # votes against
    posts.votes_total   # votes total
    

    如果您不想使用该插件,那么我将按如下方式处理您的场景:

    我假设模型之间存在以下关系。

    class User < ActiveRecord::Base
      has_many :posts
      has_many :votes, :through => :posts
    end
    
    class Post < ActiveRecord::Base
      belongs_to :user
      has_many :votes
    end
    
    class Vote < ActiveRecord::Base
      belongs_to :post
    end
    

    1.1) 统计所有用户的投票

    Vote.count  # all
    Vote.count(:conditions => {:vote => true}) # all for
    Vote.count(:conditions => {:vote => false}) # all against
    

    1.2) 查找用户的投票

    user.votes.count # all
    user.votes.count(:conditions => {:vote => true}) # all for
    user.votes.count(:conditions => {:vote => false}) # all against
    

    2.1) 投票最多的用户

    # You can add the limit clause to restrict the rows
    User.find(:all, :select => "users.*, count(votes.id) AS count", 
                    :joins => [:posts, :votes],  
                    :conditions => [" votes.vote = ? ", true],
                    :group => "votes.id", :order => "count DESC")
    

    2.2) 投票最多的帖子

    # You can add the limit clause to restrict the rows
    Post.find(:all, :select => "posts.*, count(votes.id) AS count", 
                    :joins => [:votes],  
                    :conditions => [" votes.vote = ? ", true],
                    :group => "votes.id", :order => "count DESC")
    

    3.1 ) 对于一个用户的总票数 参考1.2.1

    【讨论】:

    • 这看起来是一个非常方便的插件。不过,我想知道的是如何处理这种查询,而不是我在这里展示的确切示例。感谢您的链接!
    • 我已经用查询更新了结果。看一看。该插件可以完成您需要的大部分事情。您将重现大量代码。
    • 完美!这些正是我所希望的示例类型。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    相关资源
    最近更新 更多