【问题标题】:php and mysql live searchphp和mysql实时搜索
【发布时间】:2016-05-09 17:42:55
【问题描述】:

我目前正在进行实时搜索,该搜索直接显示来自 mysql 数据库的结果。

代码有效,但不是我想要的。

让我们从一个例子开始,这样更容易理解:

我的数据库有 5 列:

id, link, description, try, keywords

在 key up 上运行 ajax 请求的脚本如下:

$("#searchid").keyup(function () {
    var searchid = encodeURIComponent($.trim($(this).val()));
    var dataString = 'search=' + searchid;
        if (searchid != '') {
           $.ajax({
              type: "POST",
              url: "results.php",
              data: dataString,
              cache: false,
              success: function (html) {
                 $("#result").html(html).show();
              }
           });
         }
        return false;
    });
});

results.php 文件看起来是这样的:

if ($db->connect_errno > 0) {
    die('Unable to connect to database [' . $db->connect_error . ']');
}

if ($_REQUEST) {
    $q = $_REQUEST['search'];

    $sql_res = "select link, description, resources, keyword from _db where description like '%$q%' or keyword like '%$q%'";
    $result = mysqli_query($db, $sql_res) or die(mysqli_error($db));

    if (mysqli_num_rows($result) == 0) {
        $display = '<div id="explainMessage" class="explainMessage">Sorry, no results found</div>';
        echo $display;
    } else {
        while ($row = $result->fetch_assoc()) {
            $link = $row['link'];
            $description = $row['description'];
            $keyword = $row['keyword'];
            $b_description = '<strong>' . $q . '</strong>';
            $b_keyword = '<strong>' . $q . '</strong>';
            $final_description = str_ireplace($q, $b_description, $description);
            $final_keyword = str_ireplace($q, $b_keyword, $keyword);

            $display = '<div class="results" id="dbResults">
                    <div>
                        <div class="center"><span class="">Description :</span><span class="displayResult">' . $final_description . '</span></div>
                        <div class="right"><span class="">Keyword :</span><span class="displayResult">' . $final_keyword . '</span></div>
                    </div>
                    <hr>
                </div>
                </div>';
            echo $display;
        }

    }
}

现在,假设我的数据库中有这一行:

id = 1
link = google.com
description = it's google
totry = 0
keywords: google, test, search

如果我在搜索栏中输入:

google, test

我有正确的结果,但如果我输入:

test, google

我没有结果,显然顺序是错误的。 所以基本上,我想要实现的是更像“标签”的东西,这样我就可以搜索正确的关键字而不必使用正确的顺序。

我可以用我当前的代码来做吗(如果是,怎么做?)或者我需要改变一些东西?

提前感谢您的任何建议。

PS:我知道这不是从数据库读取的最佳方式,因为它存在一些安全问题,我稍后会更改它,因为这是我多年前编写的旧脚本,我更感兴趣让它正常工作,之后我将改变方法。

【问题讨论】:

    标签: php mysql ajax


    【解决方案1】:

    规范化您的架构

    关系型数据库的规则很简单(至少前三个)。

    关键词:谷歌、测试、搜索

    ...违反第二条规则。每个关键字都应该在相关表中的自己的行中。然后你可以简单地把你的查询写成....

    SELECT link, description, resources, keyword 
    FROM _db 
    INNER JOIN keywords 
    ON _db.id=keywords.db_id
    WHERE keyword.value IN (" . atomize($q) . ")
    

    (其中 atomize 分解查询字符串,将 mysqli_escape_paramter() 应用于每个条目以避免破坏您的代码,将每个术语括在单引号中并连接结果)。

    或者,您可以使用 MySQL's full text indexing 透明地为您执行此操作。

    虽然飓风在他/她的回答中提出了一些好的观点,但他们没有提到那里提出的所有解决方案都不能以任何效率处理大量数据(将字段分解为新表/使用全文索引确实)。

    【讨论】:

    • 我使用我选择的答案解决了这个问题,但我想我也会尝试这个解决方案。谢谢!
    【解决方案2】:

    未经测试的代码但根据您的需要进行修改,

    $q = $_REQUEST['search'];
    
    $q_comma = explode(",", $q);
    
    $where_in_set = '';
    
    $count = count($q_comma);
    
    foreach( $q_comma as $q)
    {
        $counter++;
        if($counter == $count) {
             $where_in_set .= "FIND_IN_SET('$q','keywords')";
         }else {
             $where_in_set .= "FIND_IN_SET('$q','keywords') OR ";
         }
    }
    
    $sql_res = "select link, description, resources, keyword from _db where $where_in_set or description like '%$q%'";
    

    【讨论】:

    • 在这个例子中,当我尝试搜索时,我收到这条消息:'where 子句'中的未知列'$q'
    • @Nick 现在检查我的编辑,我使用单引号是问题所在
    • 好的,现在消息有点不同了......如果我输入“test”,我会在“where子句”中得到未知列“test”
    • 回显你的 $sql_res 并提供
    【解决方案3】:

    首先正如你所说的这不是一个好方法。我认为您正在编写一个自动完成程序。

    1. 单词分隔符

    “google, test”或“test, google”是附加词。首先,您需要为用户定义一个分隔符。通常它是一个空格''。

    当你定义它时,你需要拆分单词。

    $words = explode(" ",$q);
    // now you get two words "google," and "test"
    

    然后你需要创建一个 sql 给你多个搜索机会。

    MySQL LIKE IN()?中有很多例子

    现在你得到你的结果了。

    1. 文本相似度

    从 db 中选择所有结果,然后从另一个文本中搜索一个文本。它给你一个相似点。最好的结果就是你的结果。

    Php Similarity Example

    重要信息

    如果你问我的意见,不要像 bcs 那样使用它,它非常昂贵。在 html 端使用自动完成器。这是example

    【讨论】:

    • 如果我已经将所有内容都存储到数据库中,我该如何使用 html 自动完成器?我的意思是,您将如何使用带有数据库数据的自动完成器来实际执行此操作?你有什么例子吗?
    • 您可以选择数据并将其作为 json 发送到 html。你可以编写一个使用这个 json 数据的搜索函数。
    【解决方案4】:

    不是一个理想的解决方案,但不是将您的搜索数据字符串视为一个元素,您可以让 php 将其视为由逗号分隔的关键字数组(通过使用explode)。然后,您将根据发送的关键字数量构建查询。

    例如,使用“google, test”您的查询将是:

    $sql_res = "select link, description, resources, keyword from _db where (description like '%$q1%' or keyword like '%$q1%') AND (description like '%$q2%' or keyword like '%$q2%')";
    

    其中 $q1 和 $q2 分别是“google”和“test”。

    【讨论】:

      【解决方案5】:

      LIKE '%google, test%' 将匹配 id=1 但不匹配 '%google,test%'(逗号之间没有空格)、'%google test%'(空格分隔符)和 '%test, google%' .将每个关键字放在单独的表中,或者您可以将输入关键字拆分为多个单个关键字并使用 OR 运算符,例如 LIKE 'google%' OR LIKE 'test%'

      【讨论】:

        【解决方案6】:

        我能想到的解决方案有两种:

        1. 使用全文index and search

        2. 1234563后一种可能会占用大量资源,因为您要在多个领域进行搜索。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-11
          • 1970-01-01
          • 2017-08-05
          • 2017-09-13
          • 2015-04-11
          • 1970-01-01
          相关资源
          最近更新 更多