【问题标题】:Find Active Record object where multiple associations match (same field)查找多个关联匹配的 Active Record 对象(相同字段)
【发布时间】:2016-06-08 23:29:59
【问题描述】:

例如,我有一个Product 和一个Favorite 关联:

class Product < ApplicationRecord
  has_many :favorites
end
class Favorite < ApplicationRecord
  belongs_to :product
  belongs_to: user
end
class User < ApplicationRecord
  has_many :favorites
end

如何找到 ID 为 1 的用户和 ID 为 2 的用户收藏的产品?更好的是,只有这两个用户收藏过的产品(没有其他人收藏过)。

我已尝试加入多个 where 查询,但未返回任何结果。我在寻找答案的过程中花了很长时间,但我真的只是碰壁了。

这是我最近的尝试:

Product.includes(:favorites).where(favorites: { user_id: 1 }).where(favorites: { user_id: 2 })

【问题讨论】:

  • 您是指两个用户都收藏的产品,还是任何一个用户都收藏的产品?
  • @dodecaphonic 两者

标签: ruby-on-rails postgresql activerecord


【解决方案1】:

如果您的意思是用户收藏的产品,您要查找的内容类似于:

Product.joins(:favorites).where(favorites: { user_id: [1, 2] })

但是,如果您正在寻找两个用户都喜欢的产品,解决方案是使用INTERSECT

SELECT products.id
FROM products INNER JOIN favorites 
  ON favorites.product_id = products.id
WHERE favorites.user_id = 1
INTERSECT
SELECT id
FROM products INNER JOIN favorites 
  ON favorites.product_id = products.id
WHERE favorites.user_id = 2

没有方便的方法将其编写为 ActiveRecord 链(即您可能会发现自己使用 find_by_sql),但在 Arel 中是可行的。

【讨论】:

  • 我收到了ActiveRecord::StatementInvalid: PG::AmbiguousColumn: ERROR: column reference "id" is ambiguous
  • 我已经可以使用 Product.joins(:favorites).where(favorites: { user_id: 1 }).merge(Product.joins(:favorites).where(favorites: { user_id: 2 }))。不过,如果不查找上述错误,我将无法找到 merge
  • 对。我应该明确限定id
  • 对。如果我没记错的话,merge 不会达到你想要的效果——反而会让后一种情况获胜。如果你传入一个数组作为参数,它只会返回一个交集。
  • 也就是说,如果它正在工作并且我弄错了,我希望你以后记得INTERSECT,因为你让数据库为你完成工作,而不是分派两个查询并计算记忆中的交集。
猜你喜欢
  • 1970-01-01
  • 2013-12-25
  • 2023-03-27
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
相关资源
最近更新 更多