Search query multiple column with OR and AND to ap

2019-07-25 08:11发布

问题:

I working on an app. I trying to implant a search system. Method is simple. On home i search a query on 3 column "name" OR "nomdep" OR "nomregion". After this, I wnat to filter by params with AND operator.

If I implant search with only one column for example "NAME" that's work, i can apply filters. But if i want to implant this with more than one OR I cant apply filter. I think OR operator is the problem. But for sure i have no idea to solve this...

Can you help me ? Thanks

camping.rb

has_many :caracteristiquetests, :foreign_key => :camping_id
has_many :situations, :foreign_key => :camping_id

    def self.searchi(query, handicap, animaux, television, plage, etang, lac)
       return scoped unless query.present?
       left_outer_joins(:caracteristiquetests, :situations).where(['nomdep LIKE ? OR name LIKE ? OR nomregion LIKE ? AND handicap LIKE ? AND animaux LIKE ? AND television LIKE ? AND plage LIKE ? AND etang LIKE ? AND lac LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%", "%#{handicap}%", "%#{animaux}%", "%#{television}%", "%#{plage}%", "%#{etang}%", "%#{lac}%"])
    end

camping_controller.rb

      def resultnohome
        if params[:query].blank?
          redirect_to action: :index and return
        else
          @campings = Camping.searchi(params[:query], params[:handicap], params[:animaux], params[:television], params[:plage], params[:etang], params[:lac])
        end
end

caracteristiquetest.rb

belongs_to :camping

situation.rb

belongs_to :camping

EDIT

I edited my model to add "()"

camping.rb

def self.searchi(query, handicap, animaux, television, plage, etang, lac)
   return scoped unless query.present?
   left_outer_joins(:caracteristiquetests, :situations).where(['(nomdep LIKE ? OR name LIKE ? OR nomregion LIKE ?) AND handicap LIKE ? AND animaux LIKE ? AND television LIKE ? AND plage LIKE ? AND etang LIKE ? AND lac LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%", "%#{handicap}%", "%#{animaux}%", "%#{television}%", "%#{plage}%", "%#{etang}%", "%#{lac}%"])
end

Unfornutualy, I m getting unexpected results : only one result is display, the first match like "Short circuit evaluation". Any ideas why ?

回答1:

Just use parentheses around the or conditions, the result of the or conditions will then be combined with the and conditions.

left_outer_joins(:caracteristiquetests, :situations).where(['(nomdep LIKE ? OR name LIKE ? OR nomregion LIKE ?) AND handicap LIKE ? AND animaux LIKE ? AND television LIKE ? AND plage LIKE ? AND etang LIKE ? AND lac LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%", "%#{handicap}%", "%#{animaux}%", "%#{television}%", "%#{plage}%", "%#{etang}%", "%#{lac}%"])

Alternatively, you can split it up into separate where statements, which will combine to make one SQL call when you retrieve the results. This would be easier to read and maintain, and doesn't do any calls where a value wasn't provided.

result = left_outer_joins(:caracteristiquetests, :situations).where('nomdep LIKE ? OR name LIKE ? OR nomregion LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%")
result = result.where('handicap LIKE ?', "%#{handicap}%") if handicap
result = result.where('animaux LIKE ?', "%#{animaux}%") if animaux
result = result.where('television LIKE ?', "%#{television}%") if television
result = result.where('plage LIKE ?', "%#{plage}%") if plage
result = result.where('etang LIKE ?', "%#{etang}%") if etange
result = result.where('lac LIKE ?', "%#{lac}%") if lac
return result