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

В моей таблице/модели есть столбец типа 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\\\"'

Ответы

Ответ 1

(Частичный ответ - приближается со стороны 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 не может быть проиндексирован.

Ответ 2

Операция '=' ищет точное совпадение, в то время как LIKE op работает больше похоже на сопоставление шаблонов с '%', похожим на '*' в регулярных выражениях.

Поэтому, если у вас есть записи с

  1. Хорошее качество
  2. Более хорошее качество

только LIKE получит оба результата.

Что касается строки escape-кода, я не уверен, где она сгенерирована, но выглядит как стандартизированное экранирование, чтобы получить это значение для SQL.

Ответ 3

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

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

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

"=" Соответствует целым сравнением строк/кусков. В то время как LIKE соответствует символу (символами) (по символам).

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

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

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

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

Ответ 4

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

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

ссылка на сайт

LIKE и = - разные операторы.

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

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 |
+--------------------------------------+