Rails:过滤 has_many_through 关联,其中所有选中的关联都存在
Rails: Filter on has_many_through association where all checked associations exist
我正在尝试构建一个复选框过滤器,它进一步减少了每个额外复选框的结果数量,其中每个复选框代表 has_many 通过关联的关系。
我有一个具有以下型号的应用程序:
- 医院
- 医院特色
- 特点
以下是协会:
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
我有一个复选框,其中列出了所有可用的功能。
<%= label_tag("helipad", "Helipad") %>
<%= check_box_tag("features[]", "helipad" %>
<%= label_tag("telesurgery", "Telesurgery") %>
<%= check_box_tag("features[]", "telesurgery" %>
<%= label_tag("emergency room", "Emergency Room") %>
<%= check_box_tag("features[]", "emergency room" %>
我正在尝试像在购物网站上那样进行过滤,其中每个选中的框进一步过滤到仅具有所有选中功能的医院。
我现在使用的查询:
hospitals = Hospital.joins(:features).where(features: {name: features} )
相反。每个额外的复选框都会增加结果的数量,因为它 return 医院具有任何一个被选中的特征,而不是医院具有所有被选中的特征。
因此,如果您检查 "helipad" 和 "telesurgery",它应该 return 只有同时具有 "helipad" 和 "telesurgery" 的医院,而不是任何具有 "helipad" 和 "telesurgery" 的医院=41=] 或 "telesurgery".
环顾四周,似乎找不到明显的解决方案。我感谢任何帮助。提前致谢。
我认为有很多选择可以做到这一点——对我来说效果很好的一个是 Sunspot Solr 过滤面。 Railscasts 解释得很好:http://railscasts.com/episodes/278-search-with-sunspot。
也许这不是最漂亮的解决方案,但它对我有用。
Hospital.joins(:features).where(features: {name: features}).group('hospitals.id').having("count(*) >= ?", features.size)
找到解决办法了。首先将医院加入到特征中,然后过滤 'features.name in (?)' 将特征数组插入到查询中。
因此,这将 return 同一家医院的每个功能都与该医院具有的相同。因此,如果列表包含 4 个特征,而一家医院拥有全部 4 个特征,则该医院将被 returned 4 次。同样,如果它只有 4 个特征中的 3 个,它会 return 3 次。
然后您按医院 ID 分组并添加 'HAVING COUNT(*)' 等于过滤后的特征数。
那么最终结果是:
hospitals = Hospital.joins(:features)
.where('features.name in (?)', searched_features)
.group("hospitals.id")
.having('COUNT(*) = ?', searched_features.length)
希望这最终能帮助到其他人。如果有人找到更优雅的方法来做到这一点,请告诉我。
使用我的 Where Exists gem:
result = Hospital.all
features.each do |feature|
result = scope.where_exists(:features, name: feature)
end
我正在尝试构建一个复选框过滤器,它进一步减少了每个额外复选框的结果数量,其中每个复选框代表 has_many 通过关联的关系。
我有一个具有以下型号的应用程序:
- 医院
- 医院特色
- 特点
以下是协会:
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
我有一个复选框,其中列出了所有可用的功能。
<%= label_tag("helipad", "Helipad") %>
<%= check_box_tag("features[]", "helipad" %>
<%= label_tag("telesurgery", "Telesurgery") %>
<%= check_box_tag("features[]", "telesurgery" %>
<%= label_tag("emergency room", "Emergency Room") %>
<%= check_box_tag("features[]", "emergency room" %>
我正在尝试像在购物网站上那样进行过滤,其中每个选中的框进一步过滤到仅具有所有选中功能的医院。
我现在使用的查询:
hospitals = Hospital.joins(:features).where(features: {name: features} )
相反。每个额外的复选框都会增加结果的数量,因为它 return 医院具有任何一个被选中的特征,而不是医院具有所有被选中的特征。
因此,如果您检查 "helipad" 和 "telesurgery",它应该 return 只有同时具有 "helipad" 和 "telesurgery" 的医院,而不是任何具有 "helipad" 和 "telesurgery" 的医院=41=] 或 "telesurgery".
环顾四周,似乎找不到明显的解决方案。我感谢任何帮助。提前致谢。
我认为有很多选择可以做到这一点——对我来说效果很好的一个是 Sunspot Solr 过滤面。 Railscasts 解释得很好:http://railscasts.com/episodes/278-search-with-sunspot。
也许这不是最漂亮的解决方案,但它对我有用。
Hospital.joins(:features).where(features: {name: features}).group('hospitals.id').having("count(*) >= ?", features.size)
找到解决办法了。首先将医院加入到特征中,然后过滤 'features.name in (?)' 将特征数组插入到查询中。
因此,这将 return 同一家医院的每个功能都与该医院具有的相同。因此,如果列表包含 4 个特征,而一家医院拥有全部 4 个特征,则该医院将被 returned 4 次。同样,如果它只有 4 个特征中的 3 个,它会 return 3 次。
然后您按医院 ID 分组并添加 'HAVING COUNT(*)' 等于过滤后的特征数。
那么最终结果是:
hospitals = Hospital.joins(:features)
.where('features.name in (?)', searched_features)
.group("hospitals.id")
.having('COUNT(*) = ?', searched_features.length)
希望这最终能帮助到其他人。如果有人找到更优雅的方法来做到这一点,请告诉我。
使用我的 Where Exists gem:
result = Hospital.all
features.each do |feature|
result = scope.where_exists(:features, name: feature)
end