Как разрешить полнотекстовый поиск с дефисами в поисковом запросе

У меня есть ключевые слова, такие как "some-or-other", где дефис имеет значение при поиске через мою базу данных 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
";

Ответ 1

Отсюда http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

Одним из решений для поиска слова с тире или дефисом является использование ПОЛНОГО ТЕКСТА ПОИСКА В РЕЖИМЕ BOOLEAN и включение слова с дефис/тире в двойные кавычки.

Или отсюда http://bugs.mysql.com/bug.php?id=2095

Существует еще одно обходное решение. Недавно он был добавлен в руководство: " Измените файл набора символов: это не требует перекомпиляции. Макрос true_word_char() использует таблицу "тип символа", чтобы отличать буквы и цифры от других персонажи., Вы можете редактировать содержимое в одном из наборов символов XML чтобы указать, что '-' является буквой. Затем используйте заданный набор символов для вашего Индексы FULLTEXT. "

Не пробовал самостоятельно.

Изменить: вот еще дополнительная информация отсюда http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html

Фраза, заключенная в символы двойной кавычки ( "" ), соответствует только строкам, которые содержат фразу буквально, поскольку она была напечатана. Полнотекстовый механизм разбивает фразу на слова и выполняет поиск в индексе FULLTEXT для слова. До MySQL 5.0.3 движок затем выполнил поиск подстроки для фразы в найденных записях, поэтому совпадение должно включать в себя несловочные символы во фразе. Начиная с MySQL 5.0.3, символы неслова не должны быть точно соответствует: поиск по фразам требует только того, чтобы совпадения содержали точно такие же слова, как фраза и в том же порядке. Например, "тестовая фраза" соответствует "test, phrase" в MySQL 5.0.3, но не раньше.

Если фраза не содержит слов, которые находятся в индексе, результат пуст. Например, если все слова являются либо временными, либо короче минимальной длины индексированных слов, результат пуст.

Ответ 2

Возможно, проще использовать оператор 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#operator_binary

Оператор Binary передает строку, следующую за ней, в двоичную строку. Это простой способ заставить сравнение столбцов выполнять байты по байтам, а не по символу. Это приводит к тому, что сравнение чувствительно к регистру, даже если столбец не определен как Binary или BLOB. Binary также приводит к значительным значениям конечных пробелов.

Ответ 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*. Слишком сложно!

И не забывайте значение len по умолчанию ft_min_word_len, поэтому поиск up-to-date возвращает только date в ваших результатах.

Trick

Из-за этого я предпочитаю трюк, поэтому конструкции с HAVING и т.д. вообще не нужны:

  • Вместо добавления в таблицу базы данных следующего текста:

    "The Up-to-Date Sorcerer" is a well-known science fiction short story.
    скопируйте дефисные слова без гипсов в конец текста внутри комментария:
    "The Up-to-Date Sorcerer" is a well-known science fiction short story.<!-- 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)

Ответ 4

Это может звучать, но после того, как я боролся с этим некоторое время, я понял, что получаю результаты, которые я хочу, удалив дефис из выражения поиска. Например, если я ищу "разделенный словами"

SELECT * FROM table WHERE MATCH(column) AGAINST ('word separated');

возвращает экземпляры "разделенных словами" по мере необходимости. Это также возвращает другие экземпляры разделенных и слов, но добавление оператора + к каждому слову достигает поиска в дефис.

SELECT * FROM table WHERE MATCH(column) AGAINST ('+word +separated');

Ответ 5

Мое предпочтительное решение состоит в том, чтобы удалить дефис из поискового запроса и из данных, в которых выполняется поиск. Я храню две колонки в моей полнотекстовой таблице - search и return. search содержит очищенные данные с удалением различных символов, и это то, с чем сравниваются поисковые запросы пользователей после того, как мой код также их очистил.

Затем я отображаю столбец return.

Это означает, что у меня есть две копии данных в моей базе данных, но для меня этот компромисс стоит того. Моя таблица FT занимает всего ~ 500 тыс. Строк, поэтому в моем случае это не имеет большого значения.