开发支持多检索词的搜索引擎所需代码

有读者问到:“我发现在search.php中,只能搜索连在一起的词,不能搜索两个分开的词,我想实现的话应该去学习哪方面的知识呢?比如我想搜“公道”,“人心”,我希望它出来的结果是公道自在人心这句话。”

要想解决这个问题,需要对搜索功能如何实现的有进一步的了解,我们通过本帖来详细分析一下。

在本书的第四章我们介绍了如何开发简易在线双语术语库,同时在博客的这个帖子中也有介绍:开发简易在线双语术语库所需代码

这位读者的上述问题就源自于这部分的学习。

搜索功能的实现

我们简单回顾一下搜索功能的实现过程:

代码一:查询框

index.php

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>STITERM</title>
</head>
<body>

<form action = "result.php" method = "POST">

<table>
<tr>
    <td>
        <input type = "text" name = "term" placeholder = "检索词" />
    </td>

    <td>
        <button type = "submit">搜索</button>
    </td>
</tr>
</table>

</form>

</body>
</html>

代码二:获取检索结果

result.php

<?php

$term = $_POST["term"];

$sql = "SELECT * FROM tm WHERE zh_CN LIKE '%$term%' OR en_US LIKE '%$term%'";

$getterm = mysqli_query($conn,$sql);

if(!$getterm)
{
    echo "无法获取术语,请检查问题!";
}
else{

    while($row = mysqli_fetch_array($getterm,MYSQLI_ASSOC))
    {
        echo $row["zh_CN"];
        echo $row["en_US"];
    }
}
?>

上面这两段代码组合到一起就能实现简易术语检索功能或简易翻译记忆功能的实现,而实现的关键在于:

1)代码一的这两行:

<form action = "result.php" method = "POST">
<input type = "text" name = "term" placeholder = "检索词" />

2)代码二的这两行:

$term = $_POST["term"];
$sql = "SELECT * FROM tm WHERE zh_CN LIKE '%$term%' OR en_US LIKE '%$term%'";

也就是说,通过代码一的表单我们可以把检索词放到“term”这个变量中(name = "term" 就表示要给输入的检索词起一个名字“term”)

通过代码二的$_POST["term"]我们就可以通过POST的方法来在两个文件之间传输检索词(代码一的method = "POST"就表示以POST方法发送数据,本书P90页有对POST方法的简要介绍)。

更为关键的是我们在代码二中构建的SQL语句:$sql = "SELECT * FROM tm WHERE zh_CN LIKE '%$term%' OR en_US LIKE '%$term%'";

如果没有SQL语句去检索数据库,我们也无法将用户输入的关键词与数据库相连。

检索词的处理

在SQL语句中,我们将用户输入的关键词放到了$term变量中,然后使用zh_CN LIKE '%$term%'en_US LIKE '%$term%'作为判断条件,看看用户输入的检索词是否出现在了中文数据中或英文数据中(OR表明的就是“或”)。

现在再看这位读者的问题:

“我发现在search.php中,只能搜索连在一起的词,不能搜索两个分开的词,我想实现的话应该去学习哪方面的知识呢?比如我想搜“公道”,“人心”,我希望它出来的结果是公道自在人心这句话。”

她说的search.php指的就是上面这两段代码对应的功能,我们上面的代码确实只能输入一个检索词,并判断这一个检索词是否出现在中文或英文数据中。

她想同时搜索两个关键词,甚至是多个关键词,上面的代码显然是做不到的。除非在index.php中我们多添加一个<input>元素,让用户输入两个检索词,如下:

代码三:支持两个检索词的搜索框

index.php

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>STITERM</title>
</head>
<body>

<form action = "result.php" method = "POST">

<table>
<tr>
    <td>
        <input type = "text" name = "term_one" placeholder = "检索词一" />
    </td>

    <td>
        <input type = "text" name = "term_two" placeholder = "检索词二" />
    </td>

    <td>
        <button type = "submit">搜索</button>
    </td>
</tr>
</table>

</form>

</body>
</html>

效果如下图:

一旦接受了两个检索词,那么result.php也得修改,如下:

<?php

$term_one = $_POST["term_one"];
$term_two = $_POST["term_two"];

//$sql = "SELECT * FROM tm WHERE zh_CN LIKE '%$term%' OR en_US LIKE '%$term%'";

$sql = "SELECT * FROM tm WHERE (zh_CN LIKE '%$term_one%' AND zh_CN LIKE '%$term_two%') OR (en_US LIKE '%$term_one%' AND en_US LIKE '%$term_two%')";

$getterm = mysqli_query($conn,$sql);

if(!$getterm)
{
    echo "无法获取术语,请检查问题!";
}
else{

    while($row = mysqli_fetch_array($getterm,MYSQLI_ASSOC))
    {
        echo $row["zh_CN"];
        echo $row["en_US"];
    }
}
?>

这里面的关键就是SQL语句的写法,大家看下面这个截图:

在这个截图中,我想搜索包含“卫生”和“中心”的句子,于是我构造的条件是:

zh_CN LIKE "%卫生%" AND zh_CN LIKE "%中心%"

也就是说我先让zh_CN对应的中文字段去查看是否有数据中包含“卫生”,然后再去看zh_CN对应的中文字段是否有包含“卫生”的数据,且两个条件必须要同时满足。

给大家再看一个实际的检索结果展示:

这个应该就与这位读者想实现的功能保持一致了。

为了帮助大家更好实践,我把代码也放到了这里:

index.php

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>STITM</title>
</head>
<body>

<form action = "result.php" method = "POST">
    <table>
        <tr>
            <td>
                <input type = "text" name = "term_one" placeholder = "检索词一" />
            </td>

            <td>
                <input type = "text" name = "term_two" placeholder = "检索词二" />

            </td>

            <td>
                <button type = "submit">搜索</button>
            </td>
        </tr>
    </table>
</form>

</body>
</html>

result.php

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">

<title>STITM</title>
</head>
<body>

<table width = "100%" border = "1">
    <tr>
        <td>序号</td>
        <td>中文</td>
        <td>英文</td>
    </tr>

<?php

$dbhost = "localhost"; //数据库所在主机地址
$dbuser = "root"; //登录服务器所用的服务器用户名
$dbpass = "root"; //登录服务器所用的用户名密码

$conn = mysqli_connect($dbhost,$dbuser,$dbpass);

if(!$conn)
{
   echo "服务器连接失败:".mysqli_connect_error();
}

mysqli_select_db($conn,"mytms");
mysqli_query($conn,"set names 'utf8'");

$term_one = $_POST["term_one"];
$term_two = $_POST["term_two"];

echo "检索词一:".$term_one."<br>";

echo "检索词二:".$term_two."<br>";
$sql = "SELECT * FROM tm WHERE (zh_CN LIKE '%$term_one%' AND zh_CN LIKE '%$term_two%') OR (en_US LIKE '%$term_one%' AND en_US LIKE '%$term_two%')";

//$sql = "SELECT * FROM tm WHERE zh_CN LIKE '%$zh_CN%' AND en_US LIKE '%$en_US%'";

$gettm = mysqli_query($conn,$sql);

if(!$gettm)
{
    echo "无法获取翻译记忆,请检查问题!";
}
else{
    while($row = mysqli_fetch_array($gettm,MYSQLI_ASSOC))
    {
        $row["zh_CN"] = preg_replace("/$term_one/u","<font color=blue><b>$term_one</b></font>",$row["zh_CN"]);

        $row["zh_CN"] = preg_replace("/$term_two/u","<font color=blue><b>$term_two</b></font>",$row["zh_CN"]);

        $row["en_US"] = preg_replace("/$term_one/u","<font color=red><b>$term_one</b></font>",$row["en_US"]);

        $row["en_US"] = preg_replace("/$term_two/u","<font color=red><b>$term_two</b></font>",$row["en_US"]);

        echo "
            <tr>
                <td>{$row['ID']}</td>
                <td>{$row['zh_CN']}</td>
                <td>{$row['en_US']}</td>
            </tr>";
    }
}
?>
</table>

</body>
</html>

(注:数据库需要自己准备,相关数据库创建的方法参见:开发简易在线翻译记忆库所需代码

检索词的进一步处理

上面的方法其实只是部分解决了这位读者的问题,因为当这位读者想搜索三个检索词时,或者搜索一个中文词、一个英文词时就会遇到问题,因为要想实现多个检索词的检索,就需要添加多个检索框,SQL语句也要跟着修改。

但我们也可以考虑使用一个检索框,用户输入的检索词用空格隔开,然后再根据空格把用户的一次输入切分成多个检索词,再将检索词放到SQL里去逐个检索。

我们在之后的教程中再介绍这个知识点。