【问题标题】:How can I find records by "count" of association using rails and mongoid?如何通过使用 rails 和 mongoid 的关联“计数”查找记录?
【发布时间】:2011-11-22 07:46:33
【问题描述】:

使用这些模型:

class Week
  has_many :proofs
end
class Proof
  belongs_to :week
end

我想做这样的事情:

Week.where(:proof.count.gt => 0)

只查找有多个证明的周。

似乎有一个答案可以解决这个问题:

Can rails scopes filter on the number of associated classes for a given field

但在本例中,Week 中没有 proof_ids 这样的属性,因为 id 与证明一起存储。这不起作用,例如:

Week.where(:proof_ids.gt => 0)

这个查询怎么可能?概念上很简单,但我不知道如何使用 mongo 或 mongoid 来做到这一点。

同样,我想按证明的数量排序,例如:

Week.desc(:proofs.size)

但这也行不通。

我确实意识到计数器缓存是我的两个具体问题的一个选项,但我也希望能够进行查询。

提前感谢您的帮助。

【问题讨论】:

    标签: ruby-on-rails mongoid has-many


    【解决方案1】:

    使用 rails(并且没有 counter_cache),您可以这样做:

    class Week < ActiveRecord::Base
      has_many :proofs
    
      def self.by_proofs_size
        sort_by { |week| week.proofs.size }
      end
    
      def self.with_at_least_n_proofs(n = 1)
        select { |week| week.proofs.size >= n }
      end
    end
    

    尽管这些操作中的每一个都会产生 2 个查询,但这远非理想。

    这对查询是重复的(=> 每个操作有 4 个查询),范围(错误?):

    scope :with_at_least_n_proofs, -> (n = 1) { select { |w| w.proofs.size >= n } }
    scope :by_proofs_size, -> { sort_by { |w| w.proofs.size } }
    

    理想的大概是使用counter_cache

    scope :with_at_least_n_proofs, -> (n = 1) { where('proofs_count >= ?', n) }
    scope :by_proofs_size, -> { order(proofs_count: :desc) }
    

    【讨论】:

    • 您可以删除 include(:proofs) 以提高性能。目前,您正在加载 :proofs 中的所有数据,而您真正需要的只是快速计数查询。试试看。
    • 它会杀死你的应用程序,因为你将收到所有周的所有证据,从数据库到你的应用程序的内存
    • @antiqe 这就是我提到使用 counter_cache 的原因
    【解决方案2】:

    我不知道这是否是最好的解决方案,因为它通过一个数组映射它,但这可以完成工作:(这里提到的其他解决方案给了我例外)

    class Week < ActiveRecord::Base
    
      scope :has_proofs, -> { any_in(:_id => includes(:proofs).select{ |w| w.proofs.size > 0 }.map{ |r| r.id }) }
    
    end
    

    【讨论】:

      【解决方案3】:

      如果我离开了,请原谅我 - 但是你能在 week 表中使用一个简单的 counter_cache 吗?然后你可以做类似 week.proofs_count 的事情。

      【讨论】:

      • 是的,正如我在问题中所说,我知道 counter_cache 是一个选项,但在这种情况下,如果可能的话,我宁愿做一个查询。如果这不起作用,那么我肯定会做计数器缓存。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多