Rails: хороший алгоритм поиска - PullRequest
0 голосов
/ 22 января 2010

Я пытаюсь вернуть результаты, более похожие на поиск

Мой текущий алгоритм такой

def search_conditions(column, q)
  vars  = []
  vars2 = []

  vars << q

  if q.size > 3
    (q.size-2).times do |i|
      vars2 << q[i..(i+2)]
      next if i == 0
      vars << q[i..-1]
      vars << q[0..(q.size-1-i)]
      vars << q[i % 2 == 0 ? (i/2)..(q.size-(i/2)) : (i/2)..(q.size-1-(i/2))] if i > 1
    end
  end

  query = "#{column} ILIKE ?"
  vars = (vars+vars2).uniq

  return [vars.map { query }.join(' OR ')] + vars.map { |x| "%#{x}%" }
end

Если я найду «Ruby on Rails», он найдет 4 способа поиска.

1) Удаление левых букв "uby on Rails" .. "ils"

2) Удаление нужных букв "Ruby on Rail" .. "Rub"

3) Удаление левой и правой букв "uby on Rails", "uby on Rail" ... "on"

4) Использование только 3 букв "Rub", "uby", "by", "y o", "on" ... "ils"

Хорошо ли использовать эти 4 способа? Там больше?

Ответы [ 3 ]

6 голосов
/ 22 января 2010

Почему вы удаляете эти буквы? Вы пытаетесь сделать так, чтобы, если кто-то ищет «виджеты», вы также соответствовали «виджетам»?

Если это так, то, что вы пытаетесь сделать, называется ' stemming ', и это действительно намного сложнее, чем удаление начальных и конечных букв. Вас также может заинтересовать удаление « стоп-слов » из вашего запроса. Это те самые распространенные слова, которые необходимы для формирования грамматически правильных предложений, но не очень полезны для поиска, такие как «a», «the» и т. Д.

Правильный поиск - чрезвычайно сложная и трудная проблема. Я бы посоветовал вам не пытаться решить ее самостоятельно, а сосредоточиться на основной цели вашего сайта. Возможно, вы можете использовать в своем коде функциональность поиска из проекта Lucene . Эта ссылка также может быть полезна для при использовании Lucene в Ruby on Rails .

Надеюсь, это поможет; Я понимаю, что я как бы обошел ваш первоначальный вопрос, но я действительно не рекомендовал бы пытаться решить этот вопрос самостоятельно.

2 голосов
/ 22 января 2010

Как говорит pkaeding, stemming слишком сложен, чтобы пытаться реализовать себя. Однако, если вы хотите искать похожие (не точные) строки в MySQL, и ваши пользовательские поисковые термины очень близки к полному значению поля базы данных (т. Е. Вы не ищете большой объем текста для слова или фразу), вы можете попробовать использовать расстояние Левенштейна . Вот реализация MySQL .

Алгоритм Левенштейна позволит вам выполнять "нечеткое" сопоставление, даст вам оценку сходства и поможет избежать установки и настройки поискового демона, что является сложным. Однако это действительно только для очень конкретного случая, а не для общего поиска по сайту.

1 голос
/ 22 января 2010

Пока все предлагали другие возможные решения, посмотрите:

Sphinx - Как вы реализуете полнотекстовый поиск для этой таблицы с 10 миллионами строк, следите за нагрузкой и сохраняете актуальность? Сфинкс хорош в таких загадках.

Думающий сфинкс - Рубиновый соединитель между сфинксом и ActiveRecord.

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