Как разрешить полнотекстовый поиск с дефисами в поисковом запросе
У меня есть ключевые слова, такие как "некоторые или другие", где дефисы имеют значение при поиске в моей базе данных mysql. В настоящее время я использую полнотекстовую функцию.
Есть ли способ избежать дефиса? Я знаю, что один из вариантов - закомментировать #define HYPHEN_IS_DELIM
в файле myisam / ftdefs.h, но, к сожалению, мой хост не позволяет этого. Есть ли другой вариант там?
Изменить 3-8-11 Вот код, который я сейчас имею:
$search_input = $_GET['search_input'];
$keyword_safe = mysql_real_escape_string($search_input);
$keyword_safe_fix = "*'\"" . $keyword_safe . "\"'*";
$sql = "
SELECT *,
MATCH(coln1, coln2, coln3) AGAINST('$keyword_safe_fix') AS score
FROM table_name
WHERE MATCH(coln1, coln2, coln3) AGAINST('$keyword_safe_fix')
ORDER BY score DESC
";
4 ответа
Отсюда http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
Одним из решений для поиска слова с дефисами или дефисами является использование ПОЛНОГО ТЕКСТОВОГО ПОИСКА В БУЛЕВОМ РЕЖИМЕ и включение слова с дефисом / тире в двойных кавычках.
Или отсюда http://bugs.mysql.com/bug.php?id=2095
Есть еще один обходной путь. Недавно оно было добавлено в руководство: "Изменить файл набора символов: для этого не требуется перекомпиляция. Макрос true_word_char () использует таблицу" тип символов "для различения букв и цифр от других символов. Вы можете редактировать содержимое одним из XML-файлы набора символов, указывающие, что "-" является "буквой". Затем используйте заданный набор символов для ваших индексов FULL TEXT ".
Не пробовал это самостоятельно.
Изменить: вот еще несколько дополнительных сведений здесь http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html
Фраза, заключенная в символы двойной кавычки ("" "), соответствует только строкам, которые содержат фразу буквально, как она была набрана. Полнотекстовая машина разбивает фразу на слова и выполняет поиск по индексу FULL TEXT для слов. До MySQL 5.0.3 механизм затем выполнял поиск подстроки для фразы в найденных записях, поэтому совпадение должно включать в фразу несловесные символы. Начиная с MySQL 5.0.3, несловные символы не должны совпадать точно: Поиск по фразе требует, чтобы совпадения содержали точно такие же слова, что и фраза, и в том же порядке, например, "тестовая фраза" соответствует "тест, фраза" в MySQL 5.0.3, но не ранее.
Если фраза не содержит слов, которые есть в индексе, результат будет пустым. Например, если все слова являются либо стоп-словами, либо короче минимальной длины индексированных слов, результат будет пустым.
Некоторые люди предложили бы использовать следующий запрос:
SELECT id
FROM texts
WHERE MATCH(text) AGAINST('well-known' IN BOOLEAN MODE)
HAVING text LIKE '%well-known%';
Но при этом вам нужно много вариантов в зависимости от используемых полнотекстовых операторов. Задача: реализовать запрос как +well-known +(>35-hour <39-hour) working week*
, Слишком сложный!
И не забудьте про лен по умолчанию ft_min_word_len
поэтому поиск up-to-date
только возвращается date
в ваших результатах.
выходка
Из-за этого я предпочитаю трюк, так что конструкции с HAVING
и т.д. не нужны вообще:
Вместо добавления следующего текста в таблицу базы данных:
"Современный колдун" - это известный научно-фантастический рассказ.
скопируйте дефисные слова без переносов в конец текста внутри комментария:"Современный колдун" - это известный научно-фантастический рассказ.
<!-- UptoDate wellknown -->
Если пользователи ищут
up-to-date
удалите дефис в запросе sql:MATCH(text) AGAINST('uptodate ' IN BOOLEAN MODE)
По этому вы можете найти пользователя up-to-date
одним словом вместо получения всех результатов, которые содержат только date
(так как ft_min_word_len
убийств up
а также to
).
Конечно перед тобой echo
тексты, которые вы должны удалить <!-- ... -->
Комментарии.
преимущества
- запрос проще
- пользователь может использовать все полнотекстовые операторы как обычно
- запрос быстрее.
- Если пользователь ищет
-well-known +science
MySQL рассматривает это какnot include *well*, could include *known* and must include *science*
, Это не то, что ожидал пользователь. Трюк тоже это решает (так как SQL-запрос ищет-wellknown +science
)
Может быть, проще использовать Binary
оператор.
SELECT *
FROM your_table_name
WHERE BINARY your_column = BINARY "Foo-Bar%AFK+LOL"
http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
BINARY
Оператор преобразует строку, следующую за ней, в двоичную строку. Это простой способ заставить сравнение столбцов выполнять побайтово, а не посимвольно. Это делает сравнение чувствительным к регистру, даже если столбец не определен как BINARY
или же BLOB
, BINARY
также приводит к тому, что конечные пробелы будут значительными
Мое предпочтительное решение состоит в том, чтобы удалить дефис из поискового термина и из данных, в которых выполняется поиск. Я держу две колонки в моей полнотекстовой таблице - search
а также return
, search
содержит очищенные данные с удаленными различными символами, и это то, с чем сравниваются поисковые запросы пользователей после того, как мой код также их очистил.
Затем я отображаю return
колонка.
Это означает, что у меня есть две копии данных в моей базе данных, но для меня этот компромисс стоит того. Моя таблица FT занимает всего ~500 тыс. Строк, поэтому в моем случае это не имеет большого значения.
Это может звучать странно, но, немного поработав с этим, я понял, что получаю желаемые результаты, удалив дефис из поискового выражения. Например, если я ищу слово "разделены словами"
SELECT * FROM table WHERE MATCH(column) AGAINST ('word separated');
возвращает экземпляры "разделенных словами" по мере необходимости. Это также возвращает другие случаи разделенного и слова, но добавляя +
Оператор для каждого слова достигает дефис поиска.
SELECT * FROM table WHERE MATCH(column) AGAINST ('+word +separated');