【问题标题】:PHP search - exclude search results that begin in the middle of a wordPHP 搜索 - 排除从单词中间开始的搜索结果
【发布时间】:2018-04-24 06:10:37
【问题描述】:

当我搜索query 时,我不想包含单词中的结果。 例如,如果我输入 "Place",我不想包含诸如 "Complacent" 这样的包含查询但不以查询开头的词。

有人可以建议一些可以阻止这种情况发生的代码吗?

$conn = mysqli_connect("localhost", "root", "", "movies");
$output = "";
    if(isset($_POST['searchVal'])){
        $searchq = $_POST['searchVal'];
        $query = mysqli_query($conn, "SELECT * FROM movielist WHERE Kids LIKE 'True' AND (Name LIKE '%$searchq%' OR Description LIKE '%$searchq%' OR Year LIKE '%$searchq%' OR Genre LIKE '%$searchq%') ORDER BY Name") or die(mysqli_error());
        $count = mysqli_num_rows($query);
        if($count == 0){
            $output = '<i>Nothing found</i>';
            } 
        else {
            while($row = mysqli_fetch_array($query)){
            $id = $row['ID'];
            $name = $row['Name'];
            $description = $row['Description'];
            $year = $row['Year'];
            $link = $row['Link'];
            $output .= '<p><a href="../player/?openMovie=' .$link. '"><b>' .$name. '</b><br><i>' .$description. ' - '.$year. '</i></a></p>';    
            }
        }       
    }
echo($output);
?>    

【问题讨论】:

标签: php search mysqli


【解决方案1】:

您可以在 LIKE 语句中省略前导 %。这将强制将搜索锚定在正在搜索的字段的开头。

LIKE 'place%' ...

会找到placementplace,但不会找到自满

LIKE '%place' ...

会找到placecommonplace,但不会complacent

LIKE '%place%' ...

会找到包含 place 的任何东西 - 包括 complacent

LIKE 'place' ...

在这里使用LIKE 等同于使用=,因为它只会找到地点

更新

对于在字符串中查找搜索词,您希望确定搜索词是完整的(而不是较长词的一部分),那么简单的LIKE 将无法完成这项工作。

使用REGEXP_LIKE 会更好,并且在正则表达式中您要明确声明搜索词的任一侧都有单词边界(或字符串的开头/结尾)。

mysql 中,正则表达式单词边界由[[:&lt;:]] 表示单词的开头,或[[:&gt;:]] 表示单词的结尾。

...
$query = mysqli_query($conn, 
    "SELECT * FROM movielist WHERE Kids LIKE 'True' 
     AND (REGEXP_LIKE(Name,'([[:<:]]|^)$searchq([[:>:]]|$)') OR 
          REGEXP_LIKE(Description,'([[:<:]]|^)$searchq([[:>:]]|$)') OR
          REGEXP_LIKE(Year,'([[:<:]]|^)$searchq([[:>:]]|$)') OR 
          REGEXP_LIKE(Genre, '([[:<:]]|^)$searchq([[:>:]]|$)'))
     ORDER BY Name") or die(mysqli_error());
...

更新 2

注意REGEXP_LIKE 不适用于旧版本的mysql,以下是替代方法(使用REGEXP)。

...
$query = mysqli_query($conn, 
    "SELECT * FROM movielist WHERE Kids LIKE 'True' 
     AND (Name REGEXP '([[:<:]]|^)$searchq([[:>:]]|$)' OR 
          Description REGEXP '([[:<:]]|^)$searchq([[:>:]]|$)' OR
          Year REGEXP '([[:<:]]|^)$searchq([[:>:]]|$)' OR 
          Genre REGEXP '([[:<:]]|^)$searchq([[:>:]]|$)')
     ORDER BY Name") or die(mysqli_error());
...

更新 3

以下内容基于 cmets 中的一些更多信息。搜索词可能是一个不完整的词,因此,有必要查找以提供的搜索词开头的词(即使搜索词本身只是部分词)

...
$query = mysqli_query($conn, 
    "SELECT * FROM movielist WHERE Kids LIKE 'True' 
     AND (Name REGEXP '([[:<:]]|^)$searchq' OR 
          Description REGEXP '([[:<:]]|^)$searchq' OR
          Year REGEXP '([[:<:]]|^)$searchq' OR 
          Genre REGEXP '([[:<:]]|^)$searchq')
     ORDER BY Name") or die(mysqli_error());
...

【讨论】:

  • 问题的上下文是电影,关键字需要出现在电影名称、描述、年份或类型中。最初的发布者想要匹配单词“Place”,例如,在一个句子的上下文中,而不是像“Complacent”这样的单词,因为它的左右有字母,它们是同一个单词的一部分。但想要匹配“离你最近的地方”之类的东西。 LIKE 将如何实现这种功能?添加空格测试?然后测试新线路?然后是对引号的测试,以及对逗号和句点的测试?等等等等?
  • @Ultimater 我同意在你的情况下,LIKE 是行不通的。
  • OP 问题的上下文显示查询SELECT * FROM movielist WHERE Kids LIKE 'True' AND (Name LIKE '%$searchq%' OR Description LIKE '%$searchq%' OR Year LIKE '%$searchq%' OR Genre LIKE '%$searchq%') ORDER BY Name。代码甚至带有 HTML 较低的 /player/?openMovie= 甚至是 $_POST['searchVal' 参数。问题的上下文显然是搜索一个充满电影信息的数据库。虽然这可能不是 OP 考虑的真正应用程序,但它是给我们的上下文,因此这就是我们要回答的上下文。
  • @Ultimater 上下文正在搜索电影数据库,这是我希望修改的实际代码。有什么可以推荐的
  • @PeterAbolins 您的第三次更新正是我所描述的场景所需的代码 - 谢谢。对于没有提供足够的信息来满足我的要求,我深表歉意。有时很难知道您需要为无数可能的场景提供什么。
猜你喜欢
  • 2018-10-10
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多