【问题标题】:Optimizing ActiveRecord query when there is if/else logic in select statement当 select 语句中有 if/else 逻辑时优化 ActiveRecord 查询
【发布时间】:2017-08-19 08:04:53
【问题描述】:

我正在尝试优化一个非常笨拙的查询。我想根据某些成员数据包逻辑返回用户记录的 activerecord 关联。

ids = User.joins(:memberships).includes(:memberships).select do |user|
  if user.memberships.count <= 1
    user.membership_packet_sent_at.blank?
  else
    user.membership_packet_sent_at.blank? && user.current_membership.created_more_than_30_days_ago?
  end
end.uniq.map(&:id)

User.where(id: ids)

我在上面遇到的问题是我必须进行两次查询,因为我不知道如何使用 select 来返回活动记录关联而不是数组。

  1. 如何从 select 中返回 activerecord 关联?
  2. 有没有更好的方法让我在选择块中组织我的逻辑?

编辑:

经过一些重构,我能够将一些选择逻辑移动到方法中:

```

ids = User.joins(:memberships)
          .where(membership_packet_sent_at: nil)
          .select(&:current_membership_packet_expired?)
          .uniq
          .map(&:id)

User.where(id: ids)

```

仍然遇到如何返回 activerecord 关联的问题

【问题讨论】:

  • 我不会说这很笨拙。初学者通常遇到的主要优化错误是 N+1(迭代内的查询),您已通过 preload 防止了这种错误。
  • @maxple 公平点。在清理了select中的方法并阅读了aegis的解决方案之后,它更有意义了。谢谢。

标签: ruby-on-rails ruby activerecord


【解决方案1】:

我认为目前无法在应用select 后直接返回Relation 对象。

这些是我能想到的主要原因:

  • Relation 对象只是一个 SQL 构建器,不能处理实际数据
  • select 方法允许执行无法表示为有效 SQL 查询的自定义进程,因此无法将 select 的结果与另一个查询(如 where)链接起来

This answer 也表达了类似的思路。

【讨论】:

    猜你喜欢
    • 2019-07-22
    • 1970-01-01
    • 2018-03-12
    • 2023-03-28
    • 2020-11-23
    • 2011-05-18
    • 1970-01-01
    • 2014-02-19
    • 1970-01-01
    相关资源
    最近更新 更多