【问题标题】:Query has_one that is a subset of a has_many查询作为 has_many 子集的 has_one
【发布时间】:2019-05-15 20:18:49
【问题描述】:

我有一些跟踪更改的多态规则,我想查询最后一个(当前)规则。我知道我可以使用belongs_to 来跟踪它,但我想保留has_one。这是模块的一点点

has_many :rule_transitions, class_name: "#{name}AppliedRuleTransition", dependent: :destroy

has_one :current_rule_transition, -> { order created_at: :desc }, class_name: "#{name}AppliedRuleTransition", inverse_of: model_name.param_key.to_sym
has_one :current_rule, through: :current_rule_transition, source: :rule

我想查询current_rule,但是rule_transitions被全部查询。

我目前的尝试是使用 postgres 的FIRST_VALUE

scope :rule, lambda { |q|
  joins(:current_rule)
  .select("#{model_name.plural}.*, rules.id = FIRST_VALUE(#{model_name.param_key}_applied_rule_transitions.rule_id) OVER(PARTITION BY #{model_name.param_key}_applied_rule_transitions.id ORDER BY #{model_name.param_key}_applied_rule_transitions.created_at DESC)")
  .where(rules: { slug: q })
}

不过,我对这个函数的理解不够好,这仍然不能满足我的需求。

【问题讨论】:

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


    【解决方案1】:

    只需改用belongs_to 并将外键放在桌子上。它将让您正确地预先加载关联以避免 n+1 问题 - 尤其是您想要记录列表和最新关联项而不加载整个关联的常见情况。

    它的性能也会比其他替代品好得多。

    belongs_to :current_rule_transition, class_name: "#{name}AppliedRuleTransition"
    has_many :rule_transitions, 
      class_name: "#{name}AppliedRuleTransition", 
      dependent: :destroy,
      after_add: ->(model, transition) { model.update(current_rule_transition: transition) }
    

    没有必要让自己变得更难。

    【讨论】:

    • 我在关联表中有大量行的应用程序中遇到了同样的问题,并尝试了各种新颖的解决方案,例如横向连接,并在让导轨包含/急切加载关联方面遇到了麻烦避免 n+1 查询以及查询本身非常慢的事实。不值得浪费精力。
    • 关于关联回调的TIL!!我正在避免这种情况,因为我不想冒险让事情变得不同步。好电话!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2012-09-18
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多