2011-05-02 112 views
0

我的表'英文'的原始名称是“数字圣莫尼卡马克杯”。如果用户尝试使用“数字马克杯”进行搜索,则不会返回带有包含数字马克杯的名称的产品。如何从使用PHP的短语中搜索随机单词?

正在使用此查询:

select * 
from english 
where((pname like '%$val%' 
     or desp1 like '%$search%' 
     or pid like '%$search%' $key_value) 
     and warehouse=0 and cid !=49) 
group by pid; 
+0

用户 - 你可以试着描述一下吗?看起来'pname'是表'english'的一个字段,但PHP变量有什么用? '$ val','$ search','$ key_value' ?? – 2011-05-02 07:00:03

+0

他们从形式的价值...感谢我实施了Gaurav查询及其工作。 – user734024 2011-05-02 07:18:09

回答

2

使用pname like '%".implode('%', explode(' ', $val))."%'代替pname like '%$val%'

在这种情况下,为了将此事。意思Digital Mug会给你结果,但MUG Digital不会。

+0

谢谢..它的工作很好.. – user734024 2011-05-02 07:17:18

+0

''%'怎么样。 str_replace('','%',$ val)。 '%')'? ;)我还建议在将'%'和'_'放入查询中之前用'\ _'在'$ val'中替换'%'。并且不要忘记sql注入... – binaryLV 2011-05-02 08:44:14

+0

@binaryLV:谢谢。 – Gaurav 2011-05-02 09:02:53

1

您可以将输入值分成两个不同的单词。为了做到这一点,做

$term_array = explode(" ", $val); 

现在,$ term_array将分别持有这两个词,你可以单独运行查询的单词。例如,您可以遍历查询两次,并对单个单词运行相同的查询。但是,这样做会导致重复(并可能导致一些不必要的结果)。尽管如此,你也许可以想到使用两个分开的单词来进行某种查询,这会产生更好的结果。

0

构建查询:

$split = explode(" ", $val); 
$qry_pname = "pname LIKE '%".implode("%' or pname LIKE '%", $split)."'%"; 

$qry = " 
SELECT * 
    FROM english 
WHERE($qry_pname 
     or desp1 like '%$search%' 
     or pid like '%$search%' $key_value) 
     and warehouse=0 and cid !=49) 
group by pid; 
"; 
1

使用该

当搜索为 Digital Mug将被视为'%Digital Mug%'它试图匹配有Digital Mug值事情是无法正常运转的The Digital Santa Monica Mug全文搜索前后有文字。

Eg : THE Digital Mug Paradise 

这样的文字将被匹配。

因此,尝试为

FULL TEXT SEARCH

1

无论是什么样的C人劝MYSQL全文搜索(拆分搜索短语和搜索每一个字),或全文搜索。


对于 “分裂的话” 的方法,我建议到:

  • 使用正则表达式的分裂,像
    preg_match_all('#[a-zA-Z0-9]+#', $text, $words);
    您不需要 搜索“$”等符号,是吗?
  • 编写一个函数,为您生成where子句。

功能产生where条款可能是这样的:

function generateFilter(array $fields, array $words) { 
    // prepare $word for putting into SQL statement 
    foreach ($words as &$word) { 
     // ensure that wildcard characters are used as regular characters 
     $word = str_replace('%', '\\%', $word); 
     $word = str_replace('_', '\\_', $word); 
     // prevent SQL injections 
     $word = mysql_real_escape_string($word); 
    } 
    unset($word); 
    // generate filter 
    $filter = array(); 
    foreach ($words as $word) { 
     $wordFilter = array(); 
     foreach ($fields as $field) { 
      $wordFilter[] = "{$field} like '%$word%'"; 
     } 
     $filter[] = implode(' or ', $wordFilter); 
    } 
    $filter = '(' . implode(') and (', $filter) . ')'; 
    return $filter; 
} 
$filter = generateFilter(
    array('name', 'surname', 'address'), 
    array('john', 'doe') 
); 
echo $filter; 

结果:

(name like '%john%' or surname like '%john%' or address like '%john%') and 
(name like '%doe%' or surname like '%doe%' or address like '%doe%') 

如果使用准备好的语句(这是高度决定),此功能将是一个有点更复杂,因为结果字符串会占用变量的占位符,而$字将被放入必须绑定到预处理语句的一些变量数组中。


“拆分词”方法适用于小字符串和少量数据。如果您有大量数据和/或大字符串,请考虑使用全文搜索。它不需要分割搜索短语,尽管它有一些限制 - 它需要用于搜索的列上的全文索引(IIRC,您可以在多个列上创建索引,然后在所有索引列上同时使用全文搜索,即,您不必特别搜索每一列),它具有最小的关键字长度,并且可能会给出非严格的结果,例如,有时候结果中可能只会出现5个关键字中的3个。尽管它给出了每个结果的相关性 - 接近搜索项的结果将具有更高的相关性。这对按相关性排序结果非常有用。

虽然创建索引似乎是您的额外工作,但它将允许DBMS比没有索引更快地执行搜索。

+0

你应该改变'str_replace'和'mysql_real_escape_string'的顺序。否则,'%'将首先由'str_replace'变为'\%',然后由'mysql_real_escape_string'变为'\\%'。 – Gumbo 2011-05-05 06:58:03

+0

@Gumbo,它可能看起来是错误的,尽管它确实有效 - 使用'mysql_query()'和MySQL控制台客户端从PHP进行测试。在数据库中的值 - ''viens%divi'','where'caluse - 'where'%viens \\%divi%''。 – binaryLV 2011-05-05 07:20:04

+0

@Gumbo,来自http://dev.mysql.com/doc/refman/5.1/en/string-comparison-functions.html - “*因为MySQL在字符串中使用C转义语法(例如,”\ n“代表一个换行符),你必须加倍你在LIKE字符串中使用的任何“\”,例如,要搜索“\ n”,将其指定为“\\ n”,要搜索“\” “\\\\”;这是因为反斜杠被解析器剥离了一次,并且当匹配模式匹配时,反斜杠被匹配。*“。所以,尽管''\%''起作用,它应该*写成''\\%''。 – binaryLV 2011-05-05 09:53:14