PHP mysql全文 bool 搜索,如何清理搜索的关键字并匹配所有单词?

标签 php mysql full-text-search

我正在尝试匹配用户输入的所有单词

我正在使用phpv7mysql v 5.7.9mysql innodb fulltext搜索 bool 模式.

但是当我在搜索中使用 @ 等特殊字符时,我的搜索不断中断。

我尝试了很多组合,我怎样才能实现这样的目标?

现在我就是这样做的。

用于获取记录数

$get_count_query = "SELECT count(*) as total_count FROM content WHERE MATCH(title) AGAINST('". mysqli_real_escape_string ($conn, $_GET['q'])."' IN BOOLEAN MODE) AND is_enabled = 1 " ;

但是如果我搜索

Adobe Premier pro -

我的查询变成

SELECT count(*) as total_count FROM content WHERE MATCH(title) AGAINST('Adobe Premier pro -' IN BOOLEAN MODE) AND is_enabled = 1  

我明白了

syntax error, unexpected $end

当末尾有特殊字符时,也会发生同样的情况。

我可以匹配所有单词。,通过在每个单词前添加 +。,

但是假设有人尝试搜索

Adobe Premier pro - tda

我的查询变成了

SELECT count(*) as total_count FROM content WHERE MATCH(title) AGAINST('+Adobe +Premier +pro - +tda' IN BOOLEAN MODE) AND is_enabled = 1  

我明白

syntax error, unexpected '+'

解决这个问题的方法是什么?

我只想允许 +-* 特殊字符作为搜索运算符。

<小时/>

更新1:

所以我尝试使用准备好的语句。,

$query = "SELECT count(*) as total_count FROM content WHERE MATCH(title) AGAINST(? IN BOOLEAN MODE) AND is_enabled = 1" ;

    if ($stmt = mysqli_prepare($conn, $query)) {

        /* bind parameters for markers */
        mysqli_stmt_bind_param($stmt, 's', $_GET['q']);

        /* execute statement */
        mysqli_stmt_execute($stmt);

        /* bind result variables */
        mysqli_stmt_bind_result($stmt, $rrow['total_count']);

        /* store result */
        mysqli_stmt_store_result($stmt);

        /* fetch values */
        while (mysqli_stmt_fetch($stmt)) {
            printr($rrow);
        }

        /* free result */
        mysqli_stmt_free_result($stmt);

        /* close statement */
        mysqli_stmt_close($stmt);
    }

/* close connection */
mysqli_close($conn);

并搜索

Adobe Premier pro -

并且输出为空白。

我在这里缺少什么?

<小时/>

更新2:

我试图复制 TPB 搜索的工作原理。到目前为止,我已经做到了,并且工作完美。 我只允许 - , * mysql 参数。, 代码很丑陋,但它确实按预期工作

//sanitize user input before sending it to db
function sanitize_keyword($keyword){

    $keyword_array = explode(' ', $keyword) ;

    $keyword_array = array_values(array_filter($keyword_array)) ;

    foreach($keyword_array as $key => $word){

        //pass it to db
/*      if (($key = array_search('(', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        } */

        //pass it to db
/*      if (($key = array_search(')', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        } */

        //dont pass it to db
        if (($key = array_search('*', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        }

        //dont pass it to db
        if (($key = array_search('+', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        } 

        //pass it to db
/*      if (($key = array_search('-', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        } */

        //dont pass it to db
        if (($key = array_search('<', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        }

        //dont pass it to db
        if (($key = array_search('>', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        }

        //dont pass it to db
        if (($key = array_search('@', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        }

        //pass it to db
/*      if (($key = array_search('~', $keyword_array)) !== false) {
            unset($keyword_array[$key]);
        } */
    }

    $keyword_array = array_values(array_filter($keyword_array)) ;

    //printr($keyword_array) ;

    $out_array = array();

    //loop through array, using increment, so we can jump to next value
    for($i=0 ; $i <= count($keyword_array); $i++){

        if(isset($keyword_array[$i])){
            //if there is space in - and word then, we get next value
            if($keyword_array[$i] == '-'){
                //get next word 
                if(isset($keyword_array[$i+1]) && strlen($keyword_array[$i+1]) > 0){
                    $out_array[] = '-'.$keyword_array[$i+1];
                    $i = $i + 1;
                }
            }elseif(isset($keyword_array[$i]) && strlen($keyword_array[$i]) > 0 && $keyword_array[$i][0] == '-'){
                //if word starts with -, then dont add + sign
                //add word as it is
                $out_array[] = $keyword_array[$i] ;
            }elseif(strpos($keyword_array[$i], '-') !== false){
                //if word contains - sign in the middle
                //explode and create words of array
                $all_words_array = explode('-', $keyword_array[$i]) ;

                //remove empty values
                $all_words_array = array_values(array_filter($all_words_array)) ;   

                //printr($all_words_array) ;

                //add each word in final array
                foreach($all_words_array as $word_t){
                    $out_array[] = '+'.$word_t;
                }
            }else{
                //its just some regular word, add it in out array
                $out_array[] = '+'.$keyword_array[$i];
            }
        }
    }

    //printr($out_array) ;
    return implode(' ', $out_array) ;
}

最佳答案

您可以轻松地使用一些 Mysql 全文搜索不支持的特殊字符来清理搜索字符串。您可以使用此功能进行逃生和清理。

/**
     * @param string $keyword
     * @return string
     */
    public function sanitizeKeyword($keyword)
    {
        $keywordArray = explode(' ', $keyword);
        $specialChar = ['*', '+', '-', ' ', '(', ')', '~', '@','%', '<', '>'];
        $finalKeywords = [];

        //loop through array, using foreach, so we can prepare proper keywords array
        foreach ($keywordArray as $keyword) {
            if (in_array($keyword, $specialChar) || empty($keyword) || strlen($keyword) < 3) {
                continue;
            }
            if (in_array(substr($keyword, 0, 1), ['+', '-','~','*', '@', '<', '>'])) {
                $keyword = substr($keyword, 1);
            }

            //add each word in final array
            $finalKeywords[] = $keyword;
        }

        // create final string with space and + sign
        $finalString = implode(' +', $finalKeywords);
        if (!empty($finalString)) {
            $finalString = '+'.$finalString;
        }

        return $finalString;
    }

关于PHP mysql全文 bool 搜索,如何清理搜索的关键字并匹配所有单词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46960221/

相关文章:

php - SQL - 改进 JOIN 查询(​​需要很长时间才能加载)

c# - 如何在 EF Core 中使用 DbFunction 翻译?

sql - 全文检索权重参数的限制是多少

mysql - Select涉及多对多表

php - mysql 语句中的计算用于评级

javascript - 将模态表单重定向到我的 php 脚本

php - 如何解决此错误 “[ErrorException] count(): Parameter must be an array or an object that implements Countable”?

android - 如何使位置自动递增并避免在 ListView 中得到重复的结果?

asp.net-mvc - 如何用MongoDB实现关键字和位置搜索?

php - MySql 使用左连接插入到 2 个不同的表中