Общее решение Ruby для SQLite3 «LIKE» или PostgreSQL «ИЛИКЕ»?

Я использую SQLite3 для разработки и PostgreSQL для развертывания. Однако я столкнулся со следующей проблемой:

Мой простой поиск с использованием SQLite3 :

 def self.search(search) if search find(:all, :conditions => ["style LIKE ? OR construction LIKE ?", "%#{search}%", "%#{search}%"]) else find(:all) end end 

Однако для PostgreSQL это не работает, и мне нужно заменить LIKE для ILIKE для решения проблемы:

 def self.search(search) if search find(:all, :conditions => ["style ILIKE ? OR construction ILIKE ?", "%#{search}%", "%#{search}%"]) else find(:all) end end 

Есть ли способ «Ruby» для этих поисков в любой базе данных?

EDIT – основываясь на ваших ответах, я не верю, что найду для вас общее решение Ruby.

Я последовал за Ruby on Rails Tutorial: Learn Rails по примеру – Michael Hartl , где последний Gemfile показывает обе базы данных … ну, неутешительно …

7 Solutions collect form web for “Общее решение Ruby для SQLite3 «LIKE» или PostgreSQL «ИЛИКЕ»?”

Здесь лежит корень проблемы :

Я использую SQLite3 для разработки и PostgreSQL для развертывания.

Это плохая идея. Вы будете продолжать сталкиваться с несовместимостями – или хуже: не осознавать их до тех пор, пока не будет нанесен ущерб.
Используйте ту же СУБД (PostgreSQL) для разработки и производства и избавьте себя от бессмысленной проблемы.


В то время как вы застряли в своей неудачной установке, есть простое исправление :

 lower(style) LIKE lower(?) 

Работает на обеих платформах.

  • Вы можете сбросить правую lower() , если вы предоставите шаблон поиска в нижнем регистре.

  • В стандартном SQLite lower(X) только сбрасываются буквы ASCII. Более того, я цитирую главу « Основные функции» в руководстве SQLite :

    Нижняя (X) функция возвращает копию строки X со всеми символами ASCII, преобразованными в нижний регистр. Встроенная функция lower () по умолчанию работает только для символов ASCII. Чтобы преобразовать случайные символы без символов ASCII, загрузите расширение ICU .

    Акцент мой.

  • PostgreSQL lower(X) работает с UTF-8 из коробки.


В качестве приветственного побочного эффекта вы можете ускорить этот запрос в PostgreSQL с индексом выражения lower(style) , который будет быстрее, чем использование ILIKE и базового индекса по style .

Кроме того, поскольку PostgreSQL 9.1 вы можете использовать индекс GIN или GIST с расширением pg_trgm для ускорения любых запросов LIKE и ILIKE – триграммы нечувствительны к регистру. Подробные инструкции и ссылки в этом связанном ответе:

  • Аналогичные строки UTF-8 для поля автозаполнения

Я думаю, что Arel – лучший способ решить эту проблему. Он используется Rails для активной записи и независим от базы данных. Ваш код будет работать одинаково в sqlite3 или postgres, который, по-видимому, соответствует вашей ситуации. Использование метода совпадений автоматически переключится на ilike в среде postgres. пример:

 users=User.arel_table User.where(users[:style].matches("%#{search}%").or(users[:construction].matches("%#{search}%"))) 

Вы можете получить дополнительную информацию от github: https://github.com/rails/arel/

Нет, нет rubyового пути для поиска базы данных. Ruby on Rails (в частности, ActiveRecord ) содержит вспомогательные методы для выполнения операций CRUD на RDB, поддерживаемых ActiveRecord, но нет лучшего способа поиска с использованием LIKE, а затем примеров вы предоставили.

Раздел документа Rails, связанный с этим обсуждением, будет ActiveRecord :: FinderMethods .

Как побочная заметка, вместо того, чтобы делать find(:all) вы можете просто сделать все .

В документах Rails используется тот же синтаксис, что и использование для выполнения инструкций LIKE, то есть:

 Person.exists?(['name LIKE ?', "%#{query}%"]) 

Использование вышеописанного метода совершенно безопасно.

Причина, по которой такие утверждения, подобные приведенным ниже, небезопасны, заключается в том, что строка where передается непосредственно в запрос базы данных без какой-либо дезинфекции, что оставляет вашу базу данных открытой для использования (т. Е. Простой апостроф в params[:first_name] может испортить весь ваш запрос и оставьте уязвимость вашей базы данных – в частности, SQL-инъекцией). В приведенном выше примере ActiveRecord может дезинфицировать параметры, которые вы передаете в запрос.

 Client.where("first_name LIKE '%#{params[:first_name]}%'") 

К сожалению, я не думаю, что вы найдете хорошее решение. Единственный другой синтаксис, ansible вам, а не: условия, заключается в использовании предложения .where:

 where(["style ILIKE ? OR construction ILIKE ?", "%#{search}%", "%#{search}%"]) 

К сожалению, как вы, вероятно, поняли, этот альтернативный синтаксис столкнется с одной и той же проблемой. Это всего лишь одно из неприятностей, с которыми вы столкнетесь, имея существенно отличающуюся среду разработки от вашей производственной среды – есть и другие довольно существенные различия между SQLite и PostgresSQL. Я бы рекомендовал просто установить Postgres на вашу машину разработки и использовать это. Это упростит процесс разработки и сделает ваш код намного чище.

Хотя squeel использовать разные базы данных в области производства и разработки, все же неплохо использовать камень squeel : https://github.com/ernie/squeel/

С его помощью вы можете написать свои запросы с помощью DSL, что легко и, возможно, намного чище и удобочитаемо, чем raw sql, и этот камень будет обрабатывать его перевод на SQL, специфичный для используемой RDBMS.

У Райана Бэйтса есть хорошее видео об этом: http://railscasts.com/episodes/354-squeel

Однажды я столкнулся с одной проблемой: вот мое решение:

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

 class AdapterSpecific class < < self def like_case_insensitive case ActiveRecord::Base.connection.adapter_name when 'PostgreSQL' 'ILIKE' else 'LIKE' end end def random #something end end 

Чтобы использовать его в своей модели:

 def self.search(search) if search find(:all, :conditions => ["style #{AdapterSpecific.like_case_insensitive} :query OR construction #{AdapterSpecific.like_case_insensitive} :query", {:query => "%#{search}%"}]) else find(:all) end end 

С момента написания, я перенес базу данных развертывания в Postgres, поскольку это намного лучше настроить по нескольким причинам (см. Другие ответы).

Вы также можете использовать полнотекстовый поиск Postgres, который сделает ваш текстовый поиск более эффективным, см. Текст для базовой реализации или pg_search, если вам нужно больше настроек.

Поиск с использованием LIKE может быть болезненным в базе данных. Конечно, он не будет использовать индекс, который может быть довольно дорогостоящим.

Более длинный ответ: я бы рекомендовал использовать Postgres в разработке (ditching sqlite3), а затем иметь полнотекстовый индекс во всех style, construction ваших поисковых полей style, construction tsvector тип tsvector Postgres.

Полнотекстовый поиск в Postgres при использовании индекса очень быстрый.

  • Почему бы не вывести параметр шаблона из конструктора?
  • Почему аргумент шаблона не может быть выведен, если он используется в качестве параметра шаблона для другого шаблона?
  • Можно ли явно указать параметры шаблона конструктора?
  • Как легко отобразить перечислимые переменные c ++ в строки
  • Как использовать class в Java?
  • Interesting Posts

    UI Design Pattern для Windows Forms (например, MVVM для WPF)

    Может ли 64-разрядное программное обеспечение работать на 32-битной ОС?

    Как я могу предотвратить копирование файлов в моем USB-накопителе?

    Как проверить идентификатор отправителя электронной почты?

    Собирать и сохранять переданные значения нескольких динамических входов HTML обратно в сервлет

    Как я могу написать функцию питания самостоятельно?

    Каков наилучший способ обрезать std :: string?

    Ярлык клавиатуры для выбора адресной строки в Total Commander

    Размер строки кешей L1 и L2

    Будет ли выравнивание «износа» на основе устройств уравнять доступ к обеим разделам SSD?

    Как отключить «прыжок» якоря при загрузке страницы?

    Предотвратите блокировку Ubuntu 14.04 на виртуальном боксе, если Windows заблокирована

    Я защищаюсь от программного обеспечения сетевого мониторинга, если используется HTTPS?

    Вложенные Ifs для личного бухгалтерского листа

    Почему 7-zip / WinRAR разархивируют файлы до «temp», прежде чем переместить их в пункт назначения?

    Давайте будем гением компьютера.