【问题标题】:Database search like google [duplicate]像谷歌这样的数据库搜索[重复]
【发布时间】:2013-11-30 01:55:11
【问题描述】:

我目前在我的 PHP+MYSQL 网站上有一个搜索选项。

MYSQL 查询目前类似于“SELECT pageurl WHERE name LIKE '%$query%'。

之所以在此发帖,是因为我注意到如果我的某件产品的名称是“Blue Bike”并且有人查找“Bike Blue”,则不会返回任何结果。

我正在寻找解决方案,因为我知道如果我在 google 上输入相同的单词,就会出现一些问题。

我正在考虑创建一个 PHP 函数来混合查询中的所有单词,如果查询包含 4 个或更少的单词,则生成大约 24 个查询。

有没有更简单的解决方案?

感谢您的宝贵时间

【问题讨论】:

  • 按单词拆分如何? WHERE name LIKE '%$word1%' AND name LIKE '%$word2%' 等?
  • 我认为您的建议可能成功了

标签: php mysql sql database search


【解决方案1】:

我写了一个函数来接近谷歌的操作,考虑到元素的双引号作为一个整体进行搜索。它不考虑 - 或 * 指令。

表:要考虑的 MySQL 表

cols:要解析的列数组

searchParams:搜索处理。例如:红野马“Florida 90210”

function naturalQueryConstructor($table, $cols, $searchParams) {

    // Basic processing and controls
    $searchParams = strip_tags($searchParams);
    if( (!$table) or (!is_array($cols)) or (!$searchParams) ) {
        return NULL;
    }
    // Start query
    $query = "SELECT * FROM $table WHERE ";

   // Explode search criteria taking into account the double quotes
    $searchParams = str_getcsv($searchParams, ' ');

   // Query writing
    foreach($searchParams as $param) {
      if(strpos($param, ' ') or (strlen($param)<4)) {
        // Elements with space were between double quotes and must be processed with LIKE.
        // Also for the elements with less than 4 characters. (red and "Florida 90210")
        $query .= "(";
        // Add each column
        foreach($cols as $col) {
            if($col) {
                $query .= $col." LIKE '%".$param."%' OR ";
            }
        }
        // Remove last ' OR ' sequence
        $query = substr($query, 0, strlen($query)-4);
        // Following criteria will added with an AND
        $query .= ") AND ";
      } else {
        // Other criteria processed with MATCH AGAINST (mustang)
        $query .= "(MATCH (";
        foreach($cols as $col) {
            if($col) {
                $query .= $col.",";
            }
        }
        // Remove the last ,
        $query = substr($query, 0, strlen($query)-1);
        // Following criteria will added with an AND
        $query .= ") AGAINST ('".$param."' IN NATURAL LANGUAGE MODE)) AND ";
      }
  }
  // Remove last ' AND ' sequence
  $query = substr($query, 0, strlen($query)-5);
  return $query;
}

感谢 stackoverflow 社区,我在这里找到了这个函数的一部分!

【讨论】:

  • 搜索的每一列都必须是“全文”并且必须解析“全文”中的每一列!
  • 另一点:MATCH AGAINST 要求提供完整的单词,意思是“musta”不会帮助找到“mustang”。所以我删除了查询构建的第二部分......
【解决方案2】:

您正在寻找的是全文搜索。 试试 Sphinx,它速度很快,并且与 MySQL 很好地集成。

Sphinx website

【讨论】:

  • 这个使用 php 吗?我下载了它,但它看起来像是基于 C++ 的。如果它确实使用了 php,请竖起大拇指
  • @JohnMax Sphinx 是独立的服务器软件。它实现了 MySQL 协议进行集成,因此您可以使用任何支持连接 MySQL 服务器的客户端。
【解决方案3】:

要进行类似 google 的搜索,您需要许多数据库和索引节点、疯狂的算法.. 现在您想出了一个 SELECT LIKE ... lol :D

MySQL 的搜索速度很慢,您需要正确设置全文和索引(MyISAM 或 Aria 引擎)。要搜索的组合或不同实体几乎无法正确且快速地实现。

我建议设置一个基于 Apache Lucene 的 Elasticsearch 服务器。 这搜索速度非常快并且易于维护。而且你不必关心SQL注入,仍然可以快速使用mysql服务器。

Elasticsearch(或其他基于 Lucene 的搜索引擎,如 SolR)可以轻松安装在任何服务器上,因为它们是用 Java 编写的。

良好的文档:

http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/current/

【讨论】:

  • 根据别人的要求或缺乏知识开玩笑,并不会让你变得更聪明或更好。
【解决方案4】:

至于在没有有效答案的情况下不要放弃:

<?php
    $search = 'this is my search';

    $searchSplit = explode(' ', $search);

    $searchQueryItems = array();
    foreach ($searchSplit as $searchTerm) {
        /*
         * NOTE: Check out the DB connections escaping part 
         * below for the one you should use.
         */
        $searchQueryItems[] = "name LIKE '%" . mysqli_real_escape_string($searchTerm) . "%'";
    }

    $query = 'SELECT pageurl FROM names' . (!empty($searchQueryItems) ? ' WHERE ' . implode(' AND ', $searchQueryItems) : '');
?>

数据库连接转义

mysqli_:

继续使用mysqli_real_escape_string 或使用$mysqli-&gt;real_escape_string($searchTerm)。

mysql_:

如果您使用mysql_,则应使用mysql_real_escape_string($searchTerm)(并考虑在已弃用时进行更改)。

PDO:

如果你使用 PDO,你应该使用trim($pdo-&gt;quote($searchTerm), "'")。

【讨论】:

    【解决方案5】:

    使用全文搜索而不是喜欢

    基于索引文本的全文搜索,比使用like 更快更好。

    有关全文搜索的更多信息,请参阅article

    【讨论】:

      【解决方案6】:

      我会先做一个explode:

      $queryArray = explode(" ", $query);
      

      然后生成类似SQL 的查询:

      for ($i=0; $i< count($queryArray); $i++) {
          $filter += " LIKE '%" + $queryArray[$i] + "%' AND" ;
      }
      $filter = rtrim ($filter, " AND");
      
      $sql = "SELECT pageurl FROM ... WHERE name " + $filter
      

      (注意:尚未测试/运行此代码)

      【讨论】:

      • 记得清理输入,如果你没有使用准备好的语句
      • 是的,你说得有道理,但我只是想粗略地表达一下这个想法。无论如何,这与@h2ooooooo 在评论中已经提到的几乎相同
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 2018-08-08
      • 2014-08-26
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 2011-06-18
      相关资源
      最近更新 更多