RAILS3: поиск, игнорирующий диакритические знаки?

#ruby-on-rails #ruby-on-rails-3 #search #diacritics

#ruby-on-rails #ruby-on-rails-3 #Поиск #диакритические знаки

Вопрос:

У меня есть приложение Rails 3, которое содержит объекты Article. У них есть атрибут title . Перед добавлением новой статьи пользователи должны выполнить поиск, чтобы узнать, существует ли уже статья с таким названием.

Сегодня кто-то сообщил о дублирующейся статье. Оказывается, тот, кто его добавил, искал его первым, но в названии был умляут над «o». Они искали без умляута, используя обычный символ «o», не нашли его и добавили дубликат.

Я делаю простой поиск по атрибуту title с областью действия, как показано ниже:

 scope :search, lambda { |term| where('title like ?', "%#{term}%") }
  

Мне интересно, есть ли простой способ «игнорировать» диакритические знаки, чтобы человек мог ввести «o» и все равно найти статью, если у o есть умляут, и то же самое для других диакритических знаков.

Я рассматривал возможность создания атрибута search_title и заполнения его самостоятельно при обновлении, заменяя диакритические знаки их обычными эквивалентами, но у этого есть свои проблемы, среди них, что, если кто-то тогда использует диакритический знак.

Я надеялся, что для этого может быть простое решение, но я не очень надеюсь. 🙂

Ответ №1:

Я предлагаю создать поле search_title и сохранить там title.to_ascii_brutal (используйте этот плагин: https://github.com/tomash/ascii_tic ). А затем измените область поиска на:

 scope :search, lambda { |term| where('search_title like ?', "%#{term.to_ascii_brutal}%") }
  

Комментарии:

1. Я решил сделать это, потому что это было быстрее и достаточно для этого приложения. (Смотрите мой ответ Ларри.) Мне пришлось изменить код, чтобы покрыть несколько отсутствующих символов. Я отправлю изменения автору. Но он отлично работает. Спасибо, Иренеуш!

Ответ №2:

Да, стандартный способ справиться с этим — поддерживать поле теневого поиска. В дополнение к изменению всех данных в Ascii, рассмотрите:

  • Меняем все на верхний регистр, чтобы устранить проблемы с регистром
  • удаление всех символов, которые не являются цифрами, буквами или пробелами. (Удалить знаки препинания, табуляции и т. Д.)
  • удаление «стоп-слов«, таких как «is», «the», «a» и т. Д. Конечно, стоп-слова зависят от языка.

Альтернативной стратегией является вычисление и поиск на основе оценки Soundex. (Или используйте исправленную версию Soundex). Для Soundex есть библиотеки Ruby или напишите свои собственные.

Soundex даст вам больше ложных срабатываний — вам нужно определить, предпочитаете ли вы иметь больше ложных срабатываний или, возможно, пропустить совпадение (ложное отрицание), потому что одно название было «Plague», а другое — «Plagues»

Вы также можете установить настоящую полнотекстовую систему поиска, либо включив систему MySQL, либо через отдельную систему.

Комментарии:

1. Спасибо за информацию, Ларри. Я решил использовать решение Иренеуша, поскольку оно было проще и достаточно для моих целей. Но я поддерживаю это, потому что это лучшее, комплексное решение, которое я бы использовал, если бы мое приложение распространялось среди многих пользователей или широкой публики. В моем приложении всего 4 внутренних пользователя!