Как сделать несколько столбцов mysql полнотекстовый поиск, где частичные слова совпадают
В настоящее время у меня есть одно поле поиска для поиска нескольких столбцов с помощью этого кода:
$searchArray = explode(" ", $searchVal);
$query="SELECT * FROM users WHERE ";
$i=0;
foreach ($searchArray as $word) {
if ($i != 0) $query .= " OR ";
$query .= " MATCH (`first_name`, `last_name`, `email`) AGAINST ('".$word."*' IN BOOLEAN MODE)";
$i++;
}
допустим у меня есть эти две строки в таблице:
id | last_name | first_name | email
1 | Smith | John | john_smith@js.com
2 | Smith | Bob | bob_smith@js.com
Если я набираю "John S", только первый результат показывает, какое поведение является желаемым.
Если я набираю "Джон Смит", только первый результат показывает, какое поведение является желаемым.
Если я набираю "Smith J", оба результата показывают, хотя Боб не соответствует.
Если Я введите "Smith John", оба результата показывают, хотя Боб не соответствует.
наконец, если я набираю "Jo S", результаты не возвращаются, несмотря на частичное совпадение на" Jo "и"S".
может ли кто-нибудь помочь мне исправить мой запрос, чтобы справиться с желаемой функциональностью заказа, не являющегося важным и частичным совпадением результатов? Если он может быть отсортирован по лучшим совпадениям (т. е. самая длинная часть слова, начиная с первой буквы, только не раздел посередине, в наибольшем количестве columns), это также было бы огромной помощью.
обновление:
просто хотел опубликовать окончательный код, который работал на основе решения. Мой цикл создания нескольких операторов соответствия был неправильным, как и мой ft_min_word_len.
мой код выглядит так:
$searchArray = explode(" ", $searchVal);
$query="SELECT * FROM users WHERE MATCH (`first_name`, `last_name`, `email`) AGAINST ('";
$i=0;
foreach ($searchArray as $word) {
$query .= "+".$word."* ";
}
$query .= "' IN BOOLEAN MODE)";
3 ответов
в логическом режиме, требуя, чтобы строки присутствовали (вместо того, чтобы просто забивать выше), делается с +
. сопоставление префиксов выполняется с окончанием *
. Кажется, это то, что вы хотите, поэтому ищите:
+John* +S*
+John* +Smith*
+Smith* +J*
+Jo* +S*
обратите внимание, что полнотекстовые индексы не могут помочь вам в поиске "в любом месте слова". что-то вроде *mith*
обязательно потерпит неудачу: они должны соответствовать символу 1 в индексе.
если вы хотите заказать их значения совпадают, и например, нужно John Smith
до Johnny Smithson
, вы бы сделали это:
SELECT * FROM user
WHERE MATCH(..fields..) AGAINST ('match' IN BOOLEAN MODE)
ORDER BY MATCH(..fields..) AGAINST ('match' IN BOOLEAN MODE) DESC;
который вы увидите никуда не приведет вас, если вы не добавите все слова>= ft_min_word_len
еще раз отдельно:
+John* +S* John
+John* +Smith* John Smith
+Smith* +J* Smith
+Jo* +S*
для последнего, оба являются ft_min_world_len по разному желанию.
см.http://dev.mysql.com/doc/refman/5.5/en//fulltext-boolean.html
вы можете поместить"+"," -", или нет оператора перед словом, чтобы заставить его искать" и содержит это слово"," не содержит это слово", и ни один оператор не"или содержит это слово"
Если я ввожу "John S", только первый результат показывает, какое поведение является желаемым.
есть только один Джон, поэтому это работает, S ниже минимальной длины слова и отброшено
Если я введу "Джон Смит", только первый результат покажет, какое поведение является желаемым.
есть только один Джон, так что это работает
Если я набираю "Smith J", оба результата показывают, хотя Боб не соответствует.
J ниже минимальной длины слова, поэтому его единственный соответствующий Смит, который является обеими строками
Если я набираю "Smith John", оба результата показывают, хотя Боб не является спичка.
поскольку вы находитесь в логическом режиме, MySQL интерпретирует это как Smith или John... Смит соответствует обоим.
наконец, если я набираю "Jo S", результаты не возвращаются, несмотря на частичное совпадение на" Jo "и"S".
Jo и S ниже минимальной длины слова-Я считаю, что MySQL рассматривает это как поиск ничего
вы хотите добавить "+" перед параметрами поиска, чтобы превратить их в и поиск... +Smith +John
IN BOOLEAN MODE
можно использовать +
- модификатор force AND
или -
-модификатор force NOT
. Нет оператора, ваш случай, означает необязательный.
и вам нужно проверить минимальную длину слова в вашей конфигурации mysql, чтобы сделать слова индекса полнотекстового индекса меньше определенной длины.
Я должен был поставить
ft_min_word_len = 2
в моем.CNF и пришлось перестроить индекс, чтобы сделать это эффективным. По умолчанию-3.
чтобы узнать свой min_word_len проверить (и upvote) этот вопрос