【问题标题】:Multiple keyword search, but exact match when there are quotation marks多个关键字搜索,但有引号时完全匹配
【发布时间】:2021-03-30 17:49:06
【问题描述】:

如果搜索vienna university,我的脚本会在某些MySQL 列中查找viennauniversity

现在,我想通过以下方式对其进行修改:如果查询包含多个以引号开头和结尾的单词(例如"vienna university"),脚本不应分隔单词,而是搜索完全匹配的vienna university 在数据库中。

如果查询是Meyer "vienna university",脚本应该在MySQL表中搜索Meyervienna university的存在。

您知道如何实现吗?

到目前为止我的代码:

<?php
$search_keyword = $_GET['query'];
//multiple keywords
$search_keyword = preg_split('/[\s]+/', $search_keyword);
$totalKeywords = count($search_keyword);
            
$sql = "SELECT * FROM `editors`
        WHERE CONCAT_WS(`journal`, `editor`, `affiliation`)
        LIKE ?";
        
//...for multiple keywords
for($i=1 ; $i < $totalKeywords; $i++){
    $sql .= " AND CONCAT_WS(`journal`, `editor`, `affiliation`)
              LIKE ?";
}
?>

【问题讨论】:

标签: php mysql regex search pdo


【解决方案1】:

这很容易用 PHP preg_* 函数完成;如果我们分步进行:

  1. 匹配并从搜索查询中删除带引号的字符串
  2. 用空格分割剩余的单词
  3. 将两个结果合并在一起

代码

为方便起见,我将代码封装在一个函数中...

function splitWords($query){

    // Matches a single or double quote followed by any character  or more
    // times followed by the same quote as in group 1. i.e. if the first capture
    // a single quote then \1 == '
    $regex = '/(\'|")(.*?)\1/';

    // Find all matches
    // Matches for the second capture group will be returned in index [2]
    preg_match_all($regex, $query, $matches);

    // Remove quoted strings from the query
    // Split on spaces IF there's still words
    if( $query = trim(preg_replace($regex, '', $query)) )
        $arr = preg_split( "/\s+/", $query );

    // Return array of split words followed by quoted strings
    // $arr ?? [] ==> If $arr doesn't exist then $arr = []
    return array_merge($arr ?? [], $matches[2]);
}


print_r( splitWords("words 'in quotes' more letters 'and quotes' and \"other quotes\" ") );

print_r( splitWords('"Anna Huber"') );

print_r( splitWords('Anna') );

输出

Array
(
    [0] => words
    [1] => more
    [2] => letters
    [3] => and
    [4] => in quotes
    [5] => and quotes
    [6] => other quotes
)

Array
(
    [0] => Anna Huber
)

Array
(
    [0] => Anna
)

【讨论】:

  • 谢谢,快到了!但是,当有引号时,它似乎返回一个空字符串作为第一个数组元素。如果查询是"Anna Huber",则似乎首先有一个空字符串,然后(作为第二个元素)Anna Huber。至少如果我先做$search_keyword = splitWords($search_keyword) 然后foreach((array) $search_keyword as $keys =&gt; $search_keyword) [...],它会循环通过两个 元素,出于某种原因,即使应该只有一个(即Anna Huber)。奇怪的是,print_r($search_keyword) 仅显示 Anna Huber 作为唯一元素。
  • @anpami 查看更新的代码以获得有效的修复!
【解决方案2】:

使用全文索引:

MATCH(col) AGAINST("vienna university") -- either word
MATCH(col) AGAINST("+vienna +university" IN BOOLEAN MODE) -- both words
MATCH(col) AGAINST('+"vienna university"') -- both words together

是的,您需要解析您的请求才能以这种方式重建它。是的,标点符号、停用词、最小字长等存在潜在问题。

速度很快。

【讨论】:

  • 在第一次使用 Steven 的回复后,我转向了您的解决方案,Rick,因为它在布尔搜索词方面确实更快更有效。我将它与PHP/MySQL Boolean Search Parserrelevant PDO codes 结合使用。谢谢你。但是,我仍然认为在史蒂文的回答中留下认可标记是公平的,因为他努力解决我的问题的狭窄范围。不过,非常感谢你,瑞克!
猜你喜欢
  • 2020-05-07
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 2019-09-22
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
  • 2018-06-19
相关资源
最近更新 更多