Как разрешить полнотекстовый поиск с дефисами в поисковом запросе - PullRequest
11 голосов
/ 04 марта 2011

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

Ответы [ 5 ]

16 голосов
/ 04 марта 2011

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

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

Или отсюда 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, несловесные символы не должны быть точно соответствует: для поиска по фразе требуется, чтобы совпадения содержали точно такие же слова, что и фраза, и в том же порядке. Например, «тестовая фраза» соответствует «тесту, фразе» в MySQL 5.0.3, но не раньше.

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

3 голосов
/ 29 января 2012

Возможно, проще использовать оператор 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 также приводит к тому, что завершающие пробелы становятся значительными.

2 голосов
/ 29 января 2017

Некоторые люди предлагают использовать следующий запрос:

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 в ваших результатах.

Трюк

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

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

    "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.<code><!-- UptoDate wellknown --></code>
  2. Если пользователи ищут up-to-date, удалите дефис в запросе sql:
    MATCH(text) AGAINST('uptodate ' IN BOOLEAN MODE)

Таким образом, вы можете найти up-to-date как одно слово вместо того, чтобы получать все результаты, содержащие только date (потому что ft_min_word_len kills up и to).

Конечно, перед вами echo текстами вы должны удалить <!-- ... --> комментарии.

Преимущества

  • запрос проще
  • пользователь может использовать все полнотекстовые операторы как обычно
  • запрос выполняется быстрее.
  • Если пользовательищет -well-known +science MySQL обрабатывает это как not include *well*, could include *known* and must include *science*.Это не то, что ожидал пользователь.Трюк тоже это решает (так как SQL-запрос ищет -wellknown +science)
0 голосов
/ 18 июня 2019

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

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

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

0 голосов
/ 08 марта 2018

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

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

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

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