Как сделать несколько столбцов 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) этот вопрос