Поиск по нескольким словам в Ruby и MySQL - PullRequest
2 голосов
/ 11 марта 2011

Я пытаюсь выполнить поиск по нескольким словам в базе данных цитат, используя Ruby, ActiveRecord и MySQL. Способ, который я сделал, показан ниже, и он работает, но я хотел бы знать, есть ли лучший способ сделать это.

# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
    query = params[:query].strip.split if params[:query]
    like = "quote LIKE "
    conditions = ""
    query.each do |word|
        conditions += (like + "'%#{word}%'")
        conditions += " AND " unless query.last == word
    end
    @quotes = Quote.all(:conditions => conditions)
end

Я хотел бы знать, есть ли лучший способ составить эту строку 'условий'. Я также попробовал использовать интерполяцию строк, например, используя оператор *, но в итоге мне потребовалась дополнительная обработка строк. Заранее спасибо

Ответы [ 4 ]

9 голосов
/ 11 марта 2011

Во-первых, я настоятельно рекомендую вам перенести логику Модели в Модели.Вместо создания логики поиска в контроллере, создайте метод #search в режиме котировки.

class Quote
  def self.search(query)
    ...
  end
end

и ваш контроллер станет

# receives a string, splits it in a array of words, create the 'conditions'
# query, and send it to ActiveRecord
def search
  @quotes = Quote.search(params[:query])
end

Теперь вернемся к исходной проблеме.Ваша существующая логика поиска делает очень плохую ошибку: она напрямую интерполирует значение, открывая ваш код для SQL-инъекции.Предполагая, что вы используете Rails 3, вы можете воспользоваться новым синтаксисом #where.

class Quote
  def self.search(query)
    words = query.to_s.strip.split
    words.inject(scoped) do |combined_scope, word|
      combined_scope.where("quote LIKE ?", "%#{word}%")
    end
  end
end

Это немного сложная тема.Если вы хотите понять, что делает combined_scope + inject, я рекомендую вам прочитать статью The Skinny on Scopes .

3 голосов
/ 14 ноября 2014

Полнотекстовый поиск MySQL не работает, поэтому лучший способ сделать это:

class Quote
  def self.search_by_quote(query)
    words = query.to_s.strip.split
    words.map! { |word| "quote LIKE '%#{word}%'" }
    sql = words.join(" AND ")
    self.where(sql)
  end
end
1 голос
/ 11 марта 2011

Лучший способ сделать это - реализовать полнотекстовый поиск. Вы можете сделать это в MySQL , но я очень рекомендую Solr . Существует множество ресурсов онлайн для реализации Solr в рельсах, но я бы рекомендовал Sunspot в качестве точки входа.

0 голосов
/ 11 марта 2011

Создание индекса FULLTEXT в MySQL.При этом вы можете оставить обработку строк в MySQL.

Пример: http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...