Поиск по столбцу типа MYSQL TEXT - PullRequest
0 голосов
/ 23 мая 2018

Моя таблица / модель имеет столбец типа 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).Смотрите это ( query # 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\\\"'

Ответы [ 4 ]

0 голосов
/ 30 мая 2018

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

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

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

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

"=" соответствует всей строкеСравнение / chunk Хотя LIKE совпадает по символу (символам) (* по символу).

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

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

Можете ли выпопробуйте это,

OtherModel.joins(:my_values).where(OtherModel[:value].eq('\\\"Good Quality\\\"'))
0 голосов
/ 28 мая 2018

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

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

link

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 |
+--------------------------------------+
0 голосов
/ 25 мая 2018

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

Так что если у вас есть записи с

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...