【问题标题】:Ruby on Rails: Search on has_many association with inner join and other conditionsRuby on Rails:使用内部连接和其他条件搜索 has_many 关联
【发布时间】:2011-06-23 11:34:49
【问题描述】:

我已经搜索了很长时间,但我无法在任何地方找到答案。 我拥有的是一个基本的搜索功能来查找房屋,一切正常,到目前为止,获取房屋的主要部分看起来像这样(例如条件):

@houses = House.all(
    :conditions => ["houses.province_id = ? AND open_houses.date > ? AND houses.surface = ?", "4", "Tue, 08 Feb 2011", "125"],
    :select => 'distinct houses.*',
    :joins => "INNER JOIN open_houses ON open_houses.house_id = houses.id" )

现在,我对房子的规格(如阳台、游泳池等)有这个 has_many 关联。 为此,我有标准设置。一个用于规范名称的表,以及一个带有 house_id 和 specification_id 的表。

但是现在,我需要将这些添加到搜索功能中。所以有人可以找到带游泳池和阳台的房子。

我确信有一个解决方案,但我只是不知道将它放在代码中的什么位置,以及如何......谷歌只是让我进入类似的页面,而不是准确解释这一点的页面。

这是我的参数的样子:

Parameters: {"dateto"=>"", "commit"=>"ZOEKEN!", "pricefrom"=>"", "location"=>"", "province_id"=>"4", "rooms"=>"", "datefrom"=>"", "surface"=>"125", "utf8"=>"✓", "priceto"=>"", "filters"=>{"by_specifications"=>["2", "5", "10"]}, "house_category_id"=>""}

希望有人能提供帮助,如果有不清楚的地方请告诉我。

谢谢

编辑: 好的,我已经开始工作了!非常感谢!

只有一个小问题:如果房子的任何一个规格存在,就会出现房子。所以这是一个 OR-OR 查询,但我想要的是 AND-AND..

因此,如果用户搜索阳台和车库,则该房屋必须仅在该房屋同时存在这两者的情况下才会出现。 我现在所做的是:对于搜索的每个规范,都在进行查询..(代码如下)

我想知道,这是正确的方法吗? 因为它有效,但我得到双重匹配..(我使用“uniq”过滤它们) uniq 的问题是我无法让“will_paginate”使用它..

这是我的最终代码:

def index
  ActiveRecord::Base.include_root_in_json = false

  # I'm creating conditions with a function I made, PM me for the code..
  conditions = createConditions( createParameters( ) );

  query = House.includes( :open_houses ).where( conditions )

  unless params[:specifications].blank?
    query = query.joins( :house_specifications )
    query = query.group( 'open_houses.id' )
    query = query.where( 'house_specifications.specification_id' => params[:specifications] )
    query = query.order( 'count(open_houses.id) DESC' )
    # query = query.having( 'count(open_houses.id) = ?', [params[:specifications].length.to_s] )
  end

  query = query.order( (params[:sort].blank?)? "open_houses.date ASC, open_houses.from ASC" : params[:sort] )

  if params[:view] == "list"
    page = params[:page] unless params[:page].blank?
    @houses = query.all.uniq.paginate( :page => page || "1", :per_page => 5 )
  else
    @houses = query.all.uniq
  end

  respond_to do |format|
    format.html
    format.js
  end
end

感谢您的帮助,非常感谢!

【问题讨论】:

  • 让我看看我是否完全理解你想要做什么。您是否只是想将 2 张桌子与 House 连接起来?我是否正确地说你有一个 [House] 模型、一个 [OpenHouse] 模型和某种 [HouseSpecifications] 连接表?是房子关系has_many :specifications, :through => :house_specifications
  • 是的,是的,请检查我所做的编辑,以便更好地了解我到目前为止所获得的内容..

标签: ruby-on-rails search join has-many


【解决方案1】:

试试这个(Rails 3):

House.joins(:houses_specifications).
      where('houses_specifications.specification_id' => params[:by_specifications]).
      where(...).all

在对查询运行最终的 .all 之前,您可以使用一堆 if 和 case 来添加过滤器、group_by、限制等。

house_query = House.where(:pink => true)
unless params[:by_specifications].blank?
  house_query = house_query.joins(:houses_specifications).
                            where('houses_specifications.specification_id' => params[:by_specifications])
end
...
@houses = house_query.all

编辑: 新的和改进的版本不直接在连接表上查询可读性,group_by 用于区分,并进行相交以获得具有所有规格的房屋。

query = House.joins(:open_houses).where(conditions)

unless params[:specifications].blank?
  query = query.joins(:specifications).
                group('houses.id').
                where(:specifications => params[:specifications]).
                having('count(*)=?', params[:specifications].count)
end

if params[:view] == "list"
  @houses = query.all.paginate(:page => params[:page])
else
  @houses = query.all
end

您可以将“有”更改为“订单”,以首先获得最匹配的规格。

【讨论】:

  • 开始工作了!谢谢!出现了另一个问题,如果可以,请在我的编辑中检查它..
  • 多个连接会杀死你的数据库,使用 group_by 用更好的方法编辑解决方案。
  • 非常好,拥有/订购的东西很棒!不得不改变一些东西,但现在它的工作方式和我想要的完全一样!检查我对最终代码的编辑。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多