Поиск столбца типа 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 работает больше похоже на сопоставление шаблонов с '%', похожим на '*' в регулярных выражениях.
Поэтому, если у вас есть записи с
- Хорошее качество
- Более хорошее качество
только 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 |
+--------------------------------------+