Полный текст MySQL обрабатывает слово e-magazine
в тексте как фразу и , а не как слово. Из-за этого это приводит к двум словам e
и magazine
. И хотя он строит поисковый индекс, он не добавляет e
к индексу из-за ft_min_word_len
(по умолчанию 4 символа).
То же ограничение длины используется для поискового запроса. По этой причине поиск e-magazine
возвращает точно такие же результаты, что и a-magazine
, поскольку a
и -
полностью игнорируются.
Но теперь вы хотите найти точную фразу e-magazine
. При этом вы используете кавычки, и это совершенно правильный способ поиска фраз, но MySQL не поддерживает операторы для фраз, только для слов:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html
С этим модификатором определенные символы имеют особое значение в начале или конце слов в строке поиска
Некоторые люди предлагают использовать следующий запрос:
SELECT id, name
FROM company
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE)
HAVING name LIKE 'e-magazi%';
Как я уже сказал, MySQL игнорирует e-
и ищет подстановочное слово magazi*
. После того, как эти результаты получены, он использует HAVING
для дополнительной фильтрации результатов для e-magazi*
, включая e-
. По этому вы найдете фразу e-magazine AG
. Конечно, HAVING
требуется только в том случае, если поисковая фраза содержит подстановочный оператор, и вы никогда не должны использовать кавычки. Этот оператор используется вашим пользователем, а не вами!
Примечание: Пока вы не окружите поисковую фразу %
, будут найдены только поля, начинающиеся с этого слова. И вы не хотите его окружать, потому что он также найдет bee-magazine
. Поэтому, возможно, вам понадобится дополнительный OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%'
, чтобы использовать его внутри текстов.
Trick
Но, наконец, я предпочитаю трюк, поэтому HAVING
совсем не нужен:
- Если вы добавляете тексты в таблицу базы данных, добавьте их дополнительно в отдельный полнотекстовый индексированный столбец и замените слова типа
up-to-date
на up-to-date uptodate
.
- Если пользователь ищет
up-to-date
, замените его в запросе на uptodate
.
Таким образом, вы все равно можете найти specific
в user-specific
, но также up-to-date
(и не только date
).
Бонус
Если пользователь ищет -well-known huge ports
, MySQL воспринимает это как not include *well*, could include *known* and *huge*
. Конечно, вы могли бы решить это и с другим дополнительным вариантом запроса, но с помощью вышеприведенного трюка вы удалили дефис, чтобы поисковый запрос выглядел просто так:
SELECT id
FROM texts
WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE)