如何进行多列mysql全文搜索,匹配部分单词

时间:2013-03-12 20:55:40

标签: php mysql sql full-text-search

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

$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不匹配,两个结果都会显示。

如果我输入“史密斯约翰”,两个结果都会显示,即使鲍勃不匹配。

最后,如果我输入“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)";

3 个答案:

答案 0 :(得分:10)

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

+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*

对于最后一个,两者都是<默认的4个字符,所以我们不能在默认的mysql中为它添加排序参数,但你可以设置ft_min_world_len不同的颜色。

答案 1 :(得分:2)

IN BOOLEAN MODE您可以使用+ - 修饰符强制AND- - 修饰符强制NOT。没有操作员,你的情况,意味着可选。

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

我必须设置

ft_min_word_len = 2
在my.cnf中

并且不得不重建索引以使其有效。默认情况下为3.

找出你的min_word_len支票(和upvote)this question

答案 2 :(得分: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是行

  

如果我输入“史密斯约翰”,两个结果都会显示,即使鲍勃不匹配。

由于你处于BOOLEAN模式,MySQL将其解释为Smith或John ... Smith匹配两者。

  

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

Jo和S低于最小字长 - 我相信MySQL认为这不会搜索任何内容

您需要在搜索参数前添加“+”才能将其转换为AND搜索... +Smith +John