首页 > 解决方案 > 如何在 Ruby on Rails 中使用 ActiveRecord 找到与完全相同的 has_many 关系集的关系?

问题描述

我有以下活动记录模型:

class House < ActiveRecord::Base
  has_many :features
end

class Feature < ActiveRecord::Base
  has_many :houses
end

如何编写一个查询来返回具有完全相同的多对多关系集的所有房屋?因此,如果房屋具有 1、2、3 的特征,我希望它们完全符合,但不包括:

仅具有特征子集的房屋(例如 1 和 2)具有该集合但包含其他特征的房屋(因此,如果它们具有特征 1、2、3 和 4,它们也应被排除)。

我怎样才能做到这一点?

标签: ruby-on-railsmany-to-manyrails-activerecord

解决方案


如果您从给定House或给定的Featuresthen 集合开始:

以下应该工作

找出House满足以下条件的 s:

  • Houses 不在具有除提供的功能之外的功能的房屋列表中
  • 特征的House总数等于提供的特征的数量
features = [1,2,3]
House.where(
  id: House.select(:id)
           .joins(:features)
           .where.not(
             id: House.select(:id)
                      .joins(:features)
                      .where.not(features: {id: features})
           )
           .group(:id)
           .having(Feature.arel_attribute(:id).count.eq(features.size))
)

SQL类似于:(假设您的连接表名为houses_features)

SELECT 
  houses.*
FROM
  houses
WHERE 
  houses.id IN ( 
     SELECT 
       houses.id 
     FROM 
       houses
       INNER JOIN houses_features ON houses.id = houses_features.house_id
       INNER JOIN features ON features.id = houses_features.feature_id
     WHERE 
       houses.id NOT IN (
         SELECT 
           houses.id 
         FROM 
           houses 
           INNER JOIN houses_features ON houses.id = houses_features.house_id
           INNER JOIN features ON features.id = houses_features.feature_id 
         WHERE 
           features.id NOT IN (1,2,3)
      )
    GROUP BY 
      houses.id
    HAVING
     COUNT(features.id) = 3
  )

推荐阅读