我有一个房地产清单,每个房地产都有一些特点。然后,我有两个桌子:
相同的real_estate可以有许多特性,相同的特性可以有很多房地产。我创建了这些模型:
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
endre_home_features.rb
class ReHomeFeature < ActiveRecord::Base
has_many :real_estate_home_features
has_many :real_estates, through: :real_estate_home_features
endreal_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)编辑1
基于@jvillian答案,我将更改我的控制器,在查询中添加一个联接。
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]我有一个房地产,其中有这三个特点。但是,在视图中,我看到同一个网站显示了3次。如果我加上不同的,房地产只显示一次。但是..。如果我将params改为:
params['home_features'] = [1 , 2, 3, 500]我没有这四个功能的房地产,但结果是一样的。没有明显的差异,房地产显示3次。有了小吃,房地产就展示了一次。预期的结果是零结果,因为我想要房地产与所有选定的功能。
但我想我们快到了!我将提供一些关于我的模型的信息:
表real_estates
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)它返回一个结果。房地产id 7。如果我去掉不同的,我有3个结果:相同的房地产,3次。
预期结果为零。如果是params['home_features'] = [1 , 2, 3],我希望得到一个结果。
编辑2
此联接方法工作正常,但返回类似于"OR“查询。在我的例子中,我需要一个带有"AND“的联接查询。查询必须是:“返回所有具有1、2和3功能的房地产”。
Tks!
发布于 2019-04-19 16:24:15
我不确定这是不是“高级搜索”。在12.1.4指定联接表的条件下的指南中包含了对已连接模型的搜索。它看起来应该是:
real_estates.joins(:re_home_features).where(re_home_features: {feature_name: 'pool'})当然,这可能不会完全奏效,因为您没有告诉我们如何找到“池功能”。但是,它应该给你正确的方向。
顺便说一下,原因是:
params['home_features'] = [1 , 2, 3, 500]返回具有any of home_features的记录是因为它使用了“或”。如果您希望real_estates包含所有的home_features,那么您需要一个‘和’。你可以在这上面到处搜索。
我想我会尝试这样的方法:
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迭代器更干净。如果你想这样做的话,你需要改变你的观点。如果您不想这样做,那么您可以回到您已经拥有的非迭代器方法。
这是没有测试的,所以我不相信它会完全按照现在的方式工作。
https://stackoverflow.com/questions/55764534
复制相似问题