【问题标题】:How can I compute a conditional sum in my model?如何在我的模型中计算条件和?
【发布时间】:2010-09-23 07:47:08
【问题描述】:

假设我想要在 Rails 中类似这样的东西:

class Proposal < ActiveRecord::Base
    def interest_level
        self.yes_votes.count - self.no_votes.count
    end

  private
    def yes_votes
        self.votes.where(:vote => true)
    end

    def no_votes
        self.votes.where(:vote => false)
    end
end
  1. 我在上面的代码中基本上做错了什么? (我意识到这可能在很多方面都很糟糕。)
  2. 从 Rails 的角度来看,正确的方法是什么?
  3. 从数据库的角度来看,我应该注意哪些注意事项? (例如,即使上面的代码 是可能的,我猜它在数据库方面也会过分。但我自然不太确定。)

【问题讨论】:

  • 你是专门要求 Rails 3 的吗(我从 .where 得到提示)?

标签: ruby-on-rails sum rails-activerecord


【解决方案1】:

类提案<:base>

def interest_level
    self.votes.sum('votes', :conditions => {:votes = true}) - self.votes.sum('votes', :conditions => {:votes = false})
end

结束

谢谢, 阿努博

【讨论】:

  • 这没有多大意义。事实上,我认为它甚至不会工作,如果 rails 允许它,它会生成两个这样的查询:SELECT SUM(votes) FROM votes WHERE votes = true AND proposal_id = .. 哪个会失败(没有名为votes 的列)。问题中的方法会生成正确的 SQL:SELECT count(1) FROM votes WHERE vote = true AND proposal_id = ..
【解决方案2】:

考虑到数据库加载,我建议实现自定义计数器缓存。我会这样做:

class Vote < ActiveRecord::Base

    def after_create
      self.update_counter_cache
    end

    def after_destroy
      self.update_counter_cache
    end

    def update_counter_cache
      self.proposal.yes_votes_count = self.proposal.votes.where(:vote=>true)
      self.proposal.no_votes_count = self.proposal.votes.where(:vote=>false)
      self.propsal.save
    end
end

请注意,您必须在 Proposal 模型中添加两​​列。

add_columns_migration.rb

add_column :proposals, :yes_votes_count, :integer
add_column :proposals, :no_votes_count, :integer

【讨论】:

  • 这可行,但它更复杂,更容易失败,并且它相对于问题中的方法的性能将基于投票更新或更改的频率。使用这种方法添加或更改投票会产生更大的成本。
  • 是的,肯定会涉及更大的成本,但我认为成本仍然比在每个页面加载时执行两个连接查询要小。此外,好的解决方案取决于您的需求、您应该如何更改投票或创建投票。
【解决方案3】:

我真的看不出你的代码有什么明显的错误。尽管有很多方法可以完成您似乎正在尝试做的事情,但您的方法似乎应该可以正常工作(尽管我对 Arel 的经验有限)。

解决此问题的另一种方法可能是简单地更改interest_level 方法:

def interest_level
    self.votes.count - self.no_votes.count * 2  # same as (total - no_votes) - no_votes
end

上面的可能会稍微快一些,但我非常怀疑它会产生很大的不同,计数查询在索引列上相当快,而且你的那个方法版本更容易阅读

【讨论】:

    猜你喜欢
    • 2021-03-21
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 2014-02-16
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多