Ruby on Rails - search in database based on a quer

2019-03-06 02:42发布

问题:

I have a simple form, where I set up a query that I want to browse, for example panasonic viera. This is on how I search the term in database:

Product.where("name ilike ?", "%#{params[:q]}%").order('price')

The query looks like %panasonic viera%, but I would need to search the query this way: %panasonic%viera% - I need to find all products, where is in the title the word panasonic or viera... but how to make this query?

回答1:

One solution would be to break up your query into individual terms and build a set of database queries connected by OR.

terms = params[:q].split
query = terms.map { |term| "name like '%#{term}%'" }.join(" OR ")
Product.where(query).order('price')


回答2:

If you're using PostgreSQL, you can use pg_search gem. It's support full text search, with option any_word:

Setting this attribute to true will perform a search which will return all models containing any word in the search terms.

Example from pg_search:

class Number < ActiveRecord::Base
  include PgSearch
  pg_search_scope :search_any_word,
                  :against => :text,
                  :using => {
                    :tsearch => {:any_word => true}
                  }

  pg_search_scope :search_all_words,
                  :against => :text
end

one = Number.create! :text => 'one'
two = Number.create! :text => 'two'
three = Number.create! :text => 'three'

Number.search_any_word('one two three') # => [one, two, three]
Number.search_all_words('one two three') # => []


回答3:

How about via ARel

def self.search(query)
  words      = query.split(/\s+/)
  table      = self.arel_table
  predicates = []

  words.each do |word|
    predicates << table[:name].matches("%#{word}%")
  end

  if predicates.size > 1
    first = predicates.shift
    conditions = Arel::Nodes::Grouping.new(predicates.inject(first) {|memo, expr| Arel::Nodes::Or.new(memo, expr)})
  else
    conditions = predicates.first
  end

  where(conditions).to_a
end


回答4:

This isn't working?

 WHERE name LIKE "panasonic" OR name LIKE "viera"