【问题标题】:How to search the random words from a phrase using PHP?如何使用 PHP 从短语中搜索随机单词?
【发布时间】:2011-05-02 06:55:52
【问题描述】:

我在“english”表中的原始 Pname 是“The Digital Santa Monica Mug”。如果用户尝试使用“Digital Mug”进行搜索,它不会返回 pname 包含 digital mug 的产品。

我正在使用这个查询:

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;

【问题讨论】:

  • 用户 - 你能试着更好地描述一下吗?似乎pname 是表english 的一个字段,但是PHP 变量是什么? $val, $search, $key_value ??
  • 它们是表单中的值...谢谢我已经实现了 Gaurav 查询及其工作。

标签: php mysql search full-text-search


【解决方案1】:

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

在这种情况下,顺序很重要。意味着Digital Mug 会给你结果,但MUG Digital 不会。

【讨论】:

  • '%' . str_replace(' ', '%', $val) . '%') 怎么样? ;) 我还建议在将 $val 中的 _ 替换为 \%_ 替换 \_,然后再将其放入查询中。并且不要忘记 sql 注入...
【解决方案2】:

使用全文搜索

当搜索为 The Digital Santa Monica Mug 时,该东西无法正常工作 Digital Mug 将被视为 '%Digital Mug%',它会尝试匹配具有 Digital Mug 之前和之后的单词的值。

Eg : THE Digital Mug Paradise

这样的文本将被匹配。

所以尝试 MYSQL 全文搜索

FULL TEXT SEARCH

【讨论】:

    【解决方案3】:

    C Man 建议的(拆分搜索短语并搜索每个单词)或全文搜索。


    对于“分词”的方法,我建议:

    • 使用正则表达式进行拆分,例如
      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%')
    

    如果你使用准备好的语句(强烈建议),这个函数会有点复杂,因为生成的字符串会有变量的占位符,而 $words 会被放入一些必须绑定到的变量数组中准备好的语句。


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

    虽然创建索引对您来说似乎是一项“额外工作”,但它可以让 DBMS 比没有索引更快地执行搜索。

    【讨论】:

    • 你应该改变str_replacemysql_real_escape_string的顺序。否则,% 将首先由 str_replace 变为 \%,然后由 mysql_real_escape_string 变为 \\%
    • @Gumbo,这似乎是错误的,尽管它确实有效 - 从 PHP 和 mysql_query() 和 MySQL 控制台客户端测试它。 DB 中的值 - 'viens%divi', where caluse - where str like '%viens\\%divi%'
    • @Gumbo, from dev.mysql.com/doc/refman/5.1/en/… - "因为 MySQL 在字符串中使用 C 转义语法(例如,“\n”表示换行符),所以必须将任何“\”加倍在 LIKE 字符串中使用。例如,要搜索“\n”,请将其指定为“\\n”。要搜索“\”,请将其指定为“\\\\”;这是因为反斜杠是由解析器剥离一次,并在进行模式匹配时再次剥离,留下一个要匹配的反斜杠。"。所以,虽然'\%' 有效,它应该写成'\\%'
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      构造查询:

      $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;
      ";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-11
        • 2021-09-13
        • 2017-03-20
        • 1970-01-01
        • 2012-10-15
        • 2020-01-16
        • 2015-08-28
        • 1970-01-01
        相关资源
        最近更新 更多