Поиск по столбцу типа MYSQL TEXT




ruby-on-rails activerecord (3)

Моя таблица / модель имеет столбец типа TEXT , и при фильтрации по записям в самой модели AR, where выдает правильный SQL и возвращает правильные результаты, вот что я имею в виду:

MyNamespace::MyValue.where(value: 'Good Quality')

Производит этот SQL:

SELECT `my_namespace_my_values`.* 
FROM `my_namespace_my_values` 
WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

Возьмите другой пример, где я присоединяюсь к MyNamespace::MyValue и фильтрую по тому же столбцу value но из другой модели (имеет отношение в модели к my_values ). Смотрите это ( запрос № 2 ):

OtherModel.joins(:my_values).where(my_values: { value: 'Good Quality' })

Это не приводит к правильному запросу, это фильтрует по столбцу value как если бы это был столбец String, а не Text, поэтому производит неправильные результаты, как это (только вставка, соответствующая где):

WHERE my_namespace_my_values`.`value` = 'Good Quality'

Теперь я могу обойти это, выполнив команду LIKE в AR, where будет получен правильный результат, но немного другой запрос. Это то, что я имею в виду :

OtherModel.joins(:my_values).where('my_values.value LIKE ?, '%Good Quality%')

Наконец-то добрались до моих вопросов. Что это такое и как это генерируется для где на модели (для типа текстового столбца)?

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

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

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

и это :

(my_namespace_my_values.value LIKE '%Good Quality%')

и что более важно, как я могу получить свой запрос с объединениями (запрос № 2), где это выглядит так :

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

Что это такое и как это генерируется для где на модели (для типа текстового столбца)?

Это сгенерировано за лексическим движком Active Records (Arel). Смотрите мой ответ ниже на ваш второй вопрос о том, почему.

Какая разница с точки зрения производительности при использовании ...

"=" Соответствует при сравнении всей строки / фрагмента, в то время как LIKE соответствует по символам (символам) (по символам).

В моих проектах я получал таблицы с миллионами строк, из моего опыта это действительно быстрее, чем использовать этот компаратор "=" или регулярное выражение, чем использование LIKE в запросе.

Как я могу получить мой запрос с объединениями (запрос № 2), где, как это ...

Можете ли вы попробовать это,

OtherModel.joins(:my_values).where(OtherModel[:value].eq('\\\"Good Quality\\\"'))

(Частичный ответ - подход со стороны MySQL.)

Что будет / не будет соответствовать

Случай 1: (Я не знаю, откуда взялись дополнительные обратные слеши и цитаты.)

WHERE `my_namespace_my_values`.`value` = '\\\"Good Quality\\\"'

\"Good Quality\"               -- matches
Good Quality                   -- does not match
The product has Good Quality.  -- does not match

Случай 2: (Найти Good Quality любом месте в value .)

WHERE my_namespace_my_values.value LIKE '%Good Quality%'

\"Good Quality\"               -- matches
Good Quality                   -- matches
The product has Good Quality.  -- matches

Случай 3:

WHERE `my_namespace_my_values`.`value` = 'Good Quality'

\"Good Quality\"               -- does not match
Good Quality                   -- matches
The product has Good Quality.  -- does not match

Спектакль:

  • Если value объявлено TEXT , все случаи медленные.
  • Если value не проиндексировано, все медленно.
  • Если value VARCHAR(255) (или меньше) и проиндексировано, случаи 1 и 3 выполняются быстрее. Он может быстро найти одну строку, вместо проверки всех строк.

Выражено по-разному:

  • LIKE с лидирующим символом подстановки ( % ) медленно.
  • Индексирование столбца важно для производительности, но TEXT не может быть проиндексирован.

Я думаю, что это может быть полезно.

чтобы найти \ n, укажите его как \ n. Для поиска \ укажите его как \\, потому что обратный слеш удаляется парсером один раз и снова, когда выполняется сопоставление с образцом, оставляя один обратный слеш для сопоставления.

link

Как и = разные операторы.

= является оператором сравнения, который работает с числами и строками. При сравнении строк оператор сравнения сравнивает целые строки.

LIKE - это строковый оператор, который сравнивает символ за символом.

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+




activerecord