Rails/MongoDb Search and Refine Search Implementation

227 Views Asked by At

I have a search functionality in my app which works as the following

  1. Homepage: user selects location from a drop-down and then enters a search key-word and searches to get a set of results
  2. Search Page (REfine Search Options): Once the user hits this page from the above he will be provided with more options to refine the search and narrow the results.

Right now we are implementing as follows but i am assuming as the paramenters increase over 5-7 the number of combinations will increase the number of if-else-elseif statement as well.

#refine search
    @search = params[:search]


    if params[:city].present? && params[:location_ids].present? && params[:search].blank?
      @blood_banks = BloodBank.where(
        { :city_id => "#{@city}" }).where(
        { :location_id.in => params[:location_ids] })
    elsif params[:search].present? && params[:location_ids].blank?
        @blood_banks = BloodBank.where(
          { :bb_name => /#@search/i })
    elsif params[:search].present? && params[:city].present? && params[:location_ids].present?
        @blood_banks = BloodBank.where(
          { :city_id => "#{@city}" }).where(
          { :location_id.in => params[:location_ids] }).where(
          { :bb_name => /#@search/i })
    end 

Which is the best way to implement the same.

How do you achieve below code,

if params[:gender].present?
      if params[:gender] == "male"
      @doctors = Doctor.where( :gender => "Male")
      end
      if params[:gender] == "female"
      @doctors = Doctor.where( :gender => "Female")
      end
      if params[:gender] == "any"
      @doctors = Doctor.where( :gender => "Male") || Doctor.where( :gender => "Female")
      end
end
1

There are 1 best solutions below

4
On

Mongoid's where returns a Mongoid::Criteria and Mongoid::Criteria responds to where by returning another Mongoid::Criteria. This means that you can build your query piece by piece:

@blood_banks = BloodBank.all
if params[:city].present?
  @blood_banks = @blood_banks.where(:city_id => params[:city])
end
if params[:location_ids].present?
  @blood_banks = @blood_banks.where(:location_id.in => params[:location_ids])
end
...

As far as the second part goes, if you're searching for any gender then just leave it out entirely, then you can do things like:

@doctors = Doctor.all
genders = { 'male' => 'Male', 'female' => 'Female' }
if genders.has_key? params[:gender]
  @doctors = @doctors.where(:gender => genders[params[:gender]]
end

Searching for any gender is the same not filtering on gender at all so the nil and 'all' cases are the same. Then you can handle the input and :gender values with a simple lookup table.