我目前正在进行实时搜索,该搜索直接从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;
});
});
在结果.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
我没有结果,因为显然顺序是错误的。所以基本上,o想要实现的更像是"标签",这样我就可以搜索正确的关键字,而不必使用正确的顺序。
我可以用我当前的代码来做吗(如果是,怎么做?(或者我需要改变一些东西?
提前感谢您的任何建议。
PS:我知道这不是从数据库读取的最佳方式,因为它有一些安全问题,我稍后会更改它,因为这是我很久以前编写的旧脚本,我更感兴趣的是让它正常工作,之后我将更改方法。
化架构
关系数据库的规则非常简单(至少前三个(。
关键字:谷歌,测试,搜索
。打破第二条规则。每个关键字都应位于相关表中自己的行中。然后,您可以简单地将查询编写为...。
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的全文索引,它可以透明地为您执行此操作。
尽管 hurricane 在他/她的回答中提出了一些很好的观点,但他们没有提到那里提出的解决方案都没有扩展以任何效率处理大量数据(将字段分解为新表/使用全文索引可以(。
未经测试的代码,但根据您的需要进行修改,
$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%'";
我能想到的有两种解决方案:
-
使用全文索引和搜索。
-
您可以在 php 中将搜索字符串拆分为单词,例如使用 explode(( 和 serach 来表示单词不是在单个 serach 标准中,而是在单独的标准中。后者可能非常耗费资源,因为您在多个领域进行搜索。
(空格分隔符( 或 '%test, google%'。将每个关键字作为单独的表格,或者您可以将输入关键字拆分为多个单个关键字并使用OR运算符,例如LIKE 'google%'或LIKE 'test%'
不是一个理想的解决方案,但你可以让 php 将其视为一个用逗号分隔的关键字数组(通过使用爆炸(,而不是将搜索数据字符串视为一个元素。然后,您将根据发送的关键字数量构建查询。
例如,使用"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%')";
其中 $q 1 和 $q 2 是"谷歌"和"测试"。
首先,正如你所说,这不是一个好方法。我认为您正在编写一个自动完成器。
- 单词分隔符
或"测试,谷歌"是一个附加词。首先,您需要为用户定义一个分隔符。通常它是一个空格''。
当你定义它时,你需要拆分单词。
$words = explode(" ",$q);
// now you get two words "google," and "test"
然后,您需要创建一个SQL来为您提供多个搜索机会。
MySQL 中有很多例子,比如 in((?
现在你得到了你的结果。
- 文本相似性
db中选择所有结果,并在一段时间内从另一个文本中搜索文本。它为您提供了一个相似性的多点。最好的结果就是你的结果。
PHP 相似性示例
重要信息
如果你问我的意见,不要像那样使用它,这是非常昂贵的。在 html 端使用自动完成器。这是一个例子