10

我目前有一个使用此代码搜索多个列的搜索字段:

$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”,则只有第一个结果会显示所需的行为。

如果我输入“John Smith”,则只有第一个结果会显示所需的行为。

如果我键入“Smith J”,即使 Bob 不匹配,两个结果都会显示。

如果我键入“Smith John”,即使 Bob 不匹配,两个结果都会显示。

最后,如果我键入“Jo S”,尽管“Jo”和“S”部分匹配,但不会返回任何结果。

谁能帮我修复我的查询以处理不重要且部分结果匹配的订单所需功能?如果它可以按最佳匹配(即单词的最长部分,仅从第一个字母开始,而不是中间的部分,列数最多)进行排序,那也将是一个巨大的帮助。

更新:

只是想发布基于解决方案的最终代码。我的循环创建多个匹配语句不正确,我的 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)";
4

3 回答 3

11

在布尔模式下,要求字符串存在(而不是仅仅得分更高),使用+. 前缀匹配以结尾完成*。这似乎是你想要的,所以搜索:

+John* +S*
+John* +Smith*
+Smith* +J*
+Jo* +S*

请注意,全文索引无法帮助您搜索“单词中的任何位置”。所以类似的东西*mith*肯定会失败:它们应该从索引中的字符 1 开始匹配。

如果您还想按匹配值对它们进行排序,例如需要John Smith before 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*

对于最后一个,两者都是 < 默认的 4 个字符,因此我们无法在默认 mysql 中为其添加排序参数,但您可以根据ft_min_world_len需要进行不同的设置。

于 2013-03-12T21:05:10.097 回答
2

IN BOOLEAN MODE您可以使用+-modifier 强制AND--modifier 强制NOT。没有运算符,您的情况,意味着可选。

并且你需要检查你的mysql配置中的最小字长,使FULLTEXT INDEX索引字小于一定长度。

我不得不设置

ft_min_word_len = 2

在 my.cnf 中,必须重建索引才能使其生效。默认情况下为 3。

要找出你的 min_word_len 检查(并投票)这个问题

于 2013-03-12T21:04:24.020 回答
2

http://dev.mysql.com/doc/refman/5.5/en//fulltext-boolean.html

您可以在单词前放置“+”、“-”或无运算符,以使其搜索“AND 包含此单词”、“NOT 包含此单词”和“没有运算符”为“OR 包含此单词”

如果我输入“John S”,则只有第一个结果会显示所需的行为。

只有一个约翰,所以这是可行的,S 低于最小字长并被丢弃

如果我输入“John Smith”,则只有第一个结果会显示所需的行为。

只有一个约翰所以这行得通

如果我键入“Smith J”,即使 Bob 不匹配,两个结果都会显示。

J 低于最小字长,所以它唯一匹配的 smith 是两行

如果我键入“Smith John”,即使 Bob 不匹配,两个结果都会显示。

由于您处于 BOOLEAN MODE MySQL 将其解释为 Smith OR John... Smith 两者都匹配。

最后,如果我键入“Jo S”,尽管“Jo”和“S”部分匹配,但不会返回任何结果。

Jo 和 S 低于最小字长 - 我相信 MySQL 将其视为无搜索

您需要在搜索参数之前添加一个“+”以将它们转换为 AND 搜索...+Smith +John

于 2013-03-12T21:09:05.100 回答