使用 count 和 ActiveRecord 进行多重连接

问题描述 投票:0回答:2

我的应用程序是关于有许多与电影相关的愿望的个人资料:

class Profile < ApplicationRecord
  has_many :wishes, dependent: :destroy
  has_many :movies, through: :wishes
end

class Wish < ApplicationRecord
  belongs_to :profile
  belongs_to :movie
end

class Movie < ApplicationRecord
  has_many :wishes, dependent: :destroy
  has_many :profiles, through: :wishes
end

我想返回 id 为 1,2 和 3 的个人资料全部“希望”的所有电影。

我设法使用原始 SQL (postgres) 获取此查询,但我想学习如何使用 ActiveRecord 来完成此查询。

select movies.id
    from movies
    join wishes on wishes.movie_id = movies.id
    join profiles on wishes.profile_id = profiles.id and profiles.id in (1,2,3)
    group by movies.id
    having count(*) = 3;

(我依赖 count(*) = 3,因为我有一个唯一的索引,可以防止使用重复的 profile_id-movie_id 对创建愿望,但我愿意接受更好的解决方案)

目前我发现的最好的方法是这个:

profiles = Profile.find([1,2,3])
Wish.joins(:profile, :movie).where(profile: profiles).group(:movie_id).count.select { |_,v| v == 3 }

(我也会用 Movie.joins 开始 AR 查询,但我没找到方法:-)

ruby-on-rails activerecord rails-activerecord
2个回答
1
投票

由于我们想要的是Movies的集合,因此ActiveRecord查询需要从Movie开始。我缺少的是我们可以在查询中指定表,例如

where(profiles: {id: profiles_ids})

这是我正在寻找的查询:(是的,使用

count
可能听起来有点脆弱,但替代方案是昂贵的 SQL 子查询。另外,我认为如果您使用多列唯一索引,它是安全的。 )

profiles_ids = [1,2,3]
Movie.joins(:profiles).where(profiles: {id: profiles_ids}).group(:id).having("COUNT(*) = ?", profiles_ids.size)

0
投票

由于belongs_to将外键放入愿望表中,您应该能够像这样查询您的个人资料:

Wish.where("profile_id IN (?)", [1,2,3]).includes(:movie).all.map{|w| w.movie}

这应该会为您提供这三个配置文件的所有电影的数组,急切地加载电影。

© www.soinside.com 2019 - 2024. All rights reserved.