我有一个房地产清单,每个房地产都有一些功能。然后,我有2张桌子:
同一个房地产可以拥有许多功能,同一个房地产可以拥有许多不动产。我创建了这些模型:
real_estate.rb
class RealEstate < ActiveRecord::Base
has_many :real_estate_home_features
has_many :re_home_features, as: :home_features, through: :real_estate_home_features, dependent: :destroy
end
re_home_features.rb
class ReHomeFeature < ActiveRecord::Base
has_many :real_estate_home_features
has_many :real_estates, through: :real_estate_home_features
end
real_estate_home_feature.rb
class RealEstateHomeFeature < ActiveRecord::Base
belongs_to :real_estate
belongs_to :re_home_feature
end
有了这个,多对多关系就可以正常工作了。
我正在搜索具有某些参数的房地产,例如:
我的搜索是这样的:
real_estates_controller.rb
def search
r = real_estates
r = r.where(code: params['code']) if params['code'].present?
r = r.where(city_name: params['city']) if params['city'].present?
r = r.where(garage: params['garage']) if params['garage'].present?
r = r.where(restrooms: params['restrooms']) if params['restrooms'].present?
r = r.paginate(:page => params[:page], :per_page => 10)
r
end
此搜索也可以正常工作。这样做没有问题,因为所有参数都在同一表的real_estates中。
但是现在,搜索有点复杂。我必须搜索具有特定功能的房地产。示例:我想要所有房地产,该房地产有4个洗手间,车库中有2辆汽车,并且有游泳池。
在我的示例中,搜索有4个洗手间和2辆汽车的房地产返回了50个房地产,但是这些房地产中只有15个有游泳池。
如何过滤这50个房地产,以仅显示与“合并功能”相关的记录?
我无法在视图中进行验证,因为每页导致错误的编号。我认为筛选器必须在数据库查询语句中位于分页符之前。
感谢您的帮助!
环境
rails -v: Rails 4.2.1
ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
so: Ubuntu 16.04.5 LTS
localhost database: MySQL (development)
server database: Postgres (production)
基于@jvillian答案,我将更改控制器,在查询中添加一个JOIN。
if params['home_features'].present? && params['home_features'].any?
r = r.joins(:re_home_features).where(re_home_features: {id: params['home_features']}).distinct(:id)
end
在我的测试中,我有:
params['home_features'] = [1 , 2, 3]
我有1个具有这3个功能的房地产。但是,在视图中,我获得了同一网站的3次展示。如果添加区别,则房地产仅显示一次。但是...如果我将参数更改为:
params['home_features'] = [1 , 2, 3, 500]
我没有具有这四个功能的房地产,但是结果是相同的。 没有区别,房地产显示3次。随着dinstict,房地产显示一次。预期结果为零结果,因为我希望房地产具有所有选定的功能。
但是我认为我们快到了!我将提供有关我的模型的一些信息:
表房地产
id | title | description | code | city_name | garage | ...
7 | Your House | Awesome... | 1234 | Rio de Janeiro | 4
表re_home_features
id | name
1 | Pool
2 | Garden
3 | Tenis court
4 | Closet
表real_estate_home_features-多对多关联
id | real_estate_id | re_home_feature_id
1 | 7 | 1
2 | 7 | 2
3 | 7 | 3
如果我跑步:
r = r.joins(:re_home_features).where(re_home_features: {id: [1,2,3,500]}).distinct(:id)
我得到了以下查询(rails控制台):
SELECT DISTINCT `real_estates`.* FROM `real_estates` INNER JOIN `real_estate_home_features` ON `real_estate_home_features`.`real_estate_id` = `real_estates`.`id` INNER JOIN `re_home_features` ON `re_home_features`.`id` = `real_estate_home_features`.`re_home_feature_id` WHERE `re_home_features`.`id` IN (1, 2, 3, 500)
它返回1个结果。不动产编号7。如果删除不重复项,我将得到3个结果:同一个不动产3次。
预期为零结果。如果params['home_features'] = [1 , 2, 3]
我希望得到1个结果。
此连接方法有效,但返回的结果类似于“ OR”查询。就我而言,我需要使用“ AND”的联接查询。查询必须为:“退还所有具有特征1 AND 2 AND 3的不动产”。
谢谢!
答案 0 :(得分:1)
我不确定这是“高级搜索”。 12.1.4 Specifying Conditions on the Joined Tables下的指南中介绍了如何搜索已加入的模型。看起来像这样:
real_estates.joins(:re_home_features).where(re_home_features: {feature_name: 'pool'})
自然,这可能不会完全起作用,因为您没有告诉我们太多有关如何找到“池功能”的信息。但是,它应该给您正确的方向。
顺便说一句,原因如下:
params['home_features'] = [1 , 2, 3, 500]
返回具有any
中的home_features
的记录是因为它采用了“或”。如果您想将real_estates
与 all home_features
一起使用,则需要一个'and'。您可以对此进行搜索。
我想我会尝试:
def search
r = real_estates.joins(:re_home_features)
%i(
code
city_name
garage
restrooms
).each do |attribute|
r = r.where(attribute => params[attribute]) unless params[attribute].blank?
end
params[:home_features].each do |home_feature_id|
r = r.where(re_home_features: {id: home_feature_id})
end unless params[:home_features].blank?
r = r.uniq
r = r.paginate(:page => params[:page], :per_page => 10)
r
end
注意:我将params[:city]
更改为params[:city_name]
,以使第一个each
迭代器更干净。如果您要这样做,则需要更改视图。如果您不想这样做,则可以返回到已有的非迭代器方法。
这没有经过测试,所以我不确定它是否可以完全按照显示的方式工作。