Ruby on rails Rails:Filter on具有多个关联,其中所有选中的关联都存在

Ruby on rails Rails:Filter on具有多个关联,其中所有选中的关联都存在,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我正在尝试构建一个复选框过滤器,它进一步减少了每个额外复选框的结果数量,其中每个复选框表示一个通过多个关联的关系 我有一个具有以下型号的应用程序: 医院 医院特征 特征 以下是协会: class Hospital < ActiveRecord::Base has_many :hospital_features has_many :features, through: :hospital_features end class HospitalFeature < ActiveR

我正在尝试构建一个复选框过滤器,它进一步减少了每个额外复选框的结果数量,其中每个复选框表示一个通过多个关联的关系

我有一个具有以下型号的应用程序:

医院 医院特征 特征 以下是协会:

class Hospital < ActiveRecord::Base
  has_many :hospital_features
  has_many :features, through: :hospital_features
end

class HospitalFeature < ActiveRecord::Base
  belongs_to :hospital
  belongs_to :feature
end

class Feature < ActiveRecord::Base
  has_many :hospital_features
  has_many :hospitals, through: :hospital_features
end
反之亦然。每选中一个额外的复选框都会增加结果的数量,因为它返回具有任何一个选中特征的医院,而不是具有所有选中特征的医院

所以,如果你检查了直升机停机坪和远程手术,它应该只返回有直升机停机坪和远程手术的医院,而不是任何有直升机停机坪或远程手术的医院


环顾四周,似乎找不到明显的解决办法。谢谢你的帮助。提前感谢。

我认为有很多方法可以实现这一点,其中一个对我来说很有效的方法是使用面对太阳黑子Solr进行过滤。铁路专家对此解释得很好:

也许这不是最漂亮的解决方案,但它对我很有效

Hospital.joins(:features).where(features: {name: features}).group('hospitals.id').having("count(*) >= ?", features.size)

找到了解决办法。首先将医院连接到要素,然后在“features.name in”处过滤,将要素数组插入查询中

因此,这将为该医院的每个功能返回相同的医院。因此,如果列表包含4个功能,并且一家医院拥有全部4个功能,那么该医院将返回4次。同样,如果它只有4个特性中的3个,它将返回3次

因此,您可以按医院id分组,并添加“HAVING COUNT*”等于过滤特征的数量

最终结果是:

  hospitals = Hospital.joins(:features)
    .where('features.name in (?)', searched_features)
    .group("hospitals.id")
    .having('COUNT(*) = ?', searched_features.length)
希望这最终能帮助别人。如果有人找到更优雅的方法,请告诉我。

使用我的宝石:


我认为这个方法的问题在于,我可以用点表示法添加AND条件。我可以通过简单地添加另一个where来实现。问题是我事先不知道要检查多少个框,所以我不知道要包括多少个框。如果有一种方法可以动态添加任意数量的where,那将是一个有效的解决方案。对不起,我收回这一点。此AR:Hospital.joins:features.where,3.wherefeature\u id=?,4生成此SQL:SELECT hospitals.*从hospitals内部连接hospital_features上的hospital_features.hospital_id=hospitals.id内部连接features上的features.id=hospital_features.id=hospitals.id=hospital_id,其中feature_id=3和feature_id=4这显然是错误的,因为一行需要有两个不同的feature_id,这是不可能的。我又迷路了,第二次尝试。你应该把这个放在另一个答案里,这样我就能看到变化了。这与我最终使用的解决方案非常相似,即:hospitals=Hospital.joins:features.where'features.name in',searched_features.grouphospitals.id.having'COUNT=?',searched_features.length这会为医院拥有的每个功能返回相同的医院。因此,如果列表包含4个功能,并且一家医院拥有全部4个功能,那么该医院将返回4次。因此,您可以按医院id分组,并添加“HAVING COUNT”等于过滤特征的数量。
Hospital.joins(:features).where(features: {name: features}).group('hospitals.id').having("count(*) >= ?", features.size)
  hospitals = Hospital.joins(:features)
    .where('features.name in (?)', searched_features)
    .group("hospitals.id")
    .having('COUNT(*) = ?', searched_features.length)
result = Hospital.all
features.each do |feature|
  result = scope.where_exists(:features, name: feature)
end