PHP+Sphinx建立高效的站内搜索引擎

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

1.    为什么要使用Sphinx
假设你现在运营着一个论坛,论坛数据已经超过100W,很多用户都反映论坛搜索的速度非常慢,那么这时你就可以考虑使用Sphinx了(当然其他的全文检索程序或方法也行)。
2.    Sphinx是什么
Sphinx由俄罗斯人Andrew Aksyonoff 开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。
全文检索是指以文档的全部文本信息作为检索对象的一种信息检索技术。检索的对象有可能是文章的标题,也有可能是文章的作者,也有可能是文章摘要或内容。
3.    Sphinx的特性
l  高速索引 (在新款CPU上,近10 MB/秒);
l  高速搜索 (2-4G的文本量中平均查询速度不到0.1秒);
l  高可用性 (单CPU上最大可支持100 GB的文本,100M文档);
l  提供良好的相关性排名
l  支持分布式搜索;
l  提供文档摘要生成;
l  提供从MySQL内部的插件式存储引擎上搜索
l  支持布尔,短语, 和近义词查询;
l  支持每个文档多个全文检索域(默认最大32个);
l  支持每个文档多属性;
l  支持断词;
l  支持单字节编码与UTF-8编码;
4. 使用Sphinx
我要使用Sphinx需要做以下几件事
1)首先得有数据
2)建立Sphinx配置文件
3)生成索引(省去)
4)启动Sphinx(省去)
5)使用之(调用api或search.exe程序进行查询)
第1件:(导入数据)
我们建立测试所需要用到得数据库、表以及数据,篇幅有限,这些在附件中都有,下载后导入MySQL即可。
第2件:(建立配置文件)
接下来我们需要建立一个Sphinx的配置文件 E:\coreseek\etc\mysql.conf,将其内容改为下面这些:

Java代码   收藏代码
  1. source mysql  
  2. {  
  3.     type                                        = mysql  
  4.     sql_host                                    = localhost  
  5.     sql_user                                    = root  
  6.     sql_pass                                    = 123456  
  7.     sql_db                                      = test  
  8.     sql_port                                    = 3306  
  9.     sql_query_pre                               = SET NAMES utf8  
  10.     sql_query                                   = SELECT id,addtime,title,content FROM post  
  11.     sql_attr_timestamp                          = addtime  
  12. }  

先讲下这个配置文件中每项的含义。
source mysql{} 定义源名称为mysql,也可以叫其他的,比如:source xxx{}
type  数据源类型
sql_* 数据相关的配置,比如sql_host,sql_pass什么的
sql_query 建立索引时的查询命令,在这里尽可能不使用where或group by,将where与groupby的内容交给sphinx,由sphinx进行条件过滤与groupby效率会更高,注意:select 的字段必须包括一个唯一主键以及要全文检索的字段,where中要用到的字段也要select出来
sql_query_pre 在执行sql_query前执行的sql命令, 可以有多条
sql_attr 以这个开头的配置项,表示属性字段,在where,orderby,groupby中出现的字段要分别定义一个属性,定义不同类型的字段要用不同的属性名,比如上面的sql_attr_timestamp就是时间戳类型。

Java代码   收藏代码
  1. index mysql  
  2. {  
  3.     source                                 = mysql  
  4.     path                                   = E:/coreseek/var/data/mysql  
  5.     charset_dictpath                       = E:/coreseek/etc/  
  6.     charset_type                           = zh_cn.utf-8  
  7. }  

index mysql{} 定义索引名称为mysql,也可以叫其他的,比如:index xxx{}
source 关联源,就是source xxx定义的。
path 索引文件存放路径,比如:E:/coreseek/var/data/mysql 实际存放在E:/coreseek/var/data/目录,然后创建多个名称为mysql后缀却不同的索引文件
charset_dictpath  指明分词法读取词典文件的位置,当启用分词法时,为必填项。在使用LibMMSeg作为分词 库时,需要确保词典文件uni.lib在指定的目录下
charset_type 字符集,比如charset_type = zh_cn.gbk

Java代码   收藏代码
  1. searchd  
  2. {  
  3.     listen                                  = 9312  
  4.     max_matches                             = 1000  
  5.     pid_file                                = E:/coreseek/var/log/searchd_mysql.pid  
  6.     log                                     = E:/coreseek/var/log/searchd_mysql.log  
  7.     query_log                               = E:/coreseek/var/log/query_mysql.log  
  8. }  

searchd{} sphinx守护进程配置
listen 监听端口
max_matches最大匹配数,也就是查找的数据再多也只返回这里设置的1000条
pid_file pid文件路径
log全文检索日志
query_log查询日志
好了,配置文件就这样,配置的参数还有很多,大家可以自己查文档。
第5步:(使用Sphinx)
在web根目录下建立一个search目录(当然不在根目录也行,同样目录名也可以随取),复制E:\coreseek\api\ sphinxapi.php文件到search目录(sphinxapi.php这个是sphinx官方提供的api),开始php程序的编写。
在search目录建立一个文件,名字叫啥都行,我管它叫index.php,其内容如下

Java代码   收藏代码
  1. <?php  
  2. include("sphinxapi.php"); //加载SphinxAPI  
  3. //分页所需参数  
  4. $page = empty($_GET['page']) ? 1 : (int)$_GET['page']; //当前第几页  
  5. $pageSize = 5//每页显示几条  
  6.   
  7. $sphinx = new SphinxClient(); // 实例化Api  
  8. $sphinx->SetServer("localhost"9312); //设置服务端,第一个参数sphinx服务器地址,第二个sphinx监听端口  
  9. $sphinx->SetMatchMode(SPH_MATCH_ANY);  
  10. $sphinx->SetLimits(($page - 1) * $pageSize, $pageSize); //传递当前页面所需的数据条数的参数  
  11. $res = $sphinx->query("sphinx""mysql"); // 第一个参数查询的关键字,第二个查询的索引名称,多个索引名称以,分开,也可以用*表示所有索引。  
  12. if ($res['total'] == 0) {  
  13.     echo '没有结果,请重新搜索';  
  14.     exit;  
  15. }  
  16. echo "<pre>";  
  17. print_r($res);  

打印结果:
Array
(
   ………省略………
    [matches] => Array
        (
            [2] => Array
                (
                    [weight] => 2
                    [attrs] => Array
                        (
                            [addtime] => 1282622004
                        )
                )
            [4] => Array
                (
                    [weight] => 2
                    [attrs] => Array
                        (
                            [addtime] => 1282622079
                        )
                )
        )
  ………省略………
)
Matches中就是查询的结果了,但是仿佛不是我们想要的数据,比如titile,content字段的内容就没有查询出来,根据官方的说明是Sphinx并没有连接到MySQL去取数据,只是根据它自己的索引内容进行计算,因此如果想用Sphinx提供的API去取得我们想要的数据,还必须以查询的结果为依据,再次查询MySQL从而得到我们想要的数据。
查询结果中键值分别表示

唯一主键
weight权重
attrs sql_attr_*中配置
至此,搜索引擎算是完成一大半了,剩下的大家可以自行完成。
比如:

Java代码   收藏代码
  1. <?php  
  2. $ids = array_keys($res['matches']); //获取主键,根据主键分表查询  
  3. $ids = join(',', $ids);  
  4. $query = mysql_query("SELECT * FROM post WHERE id IN ({$ids})");  
  5. while ($row = mysql_fetch_assoc($query)) {  
  6. }  

Sphinx的更多配置,程序的参数等,大家可以查看Sphinx的文档。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
自然语言处理 关系型数据库 MySQL
php sphinx 全文检索 中文分词
php sphinx 全文检索 中文分词
147 0
|
jenkins Linux 持续交付
sphinx(五)php执行sphinx更新索引rotate命令
选择在更新数据的时候更新索引,这样做是为了保证数据检索的实时性,但是如果您的数据需要比较频繁的更新且数据量比较大,并且对数据检索没有实时性的要求,那么可以使用linux的定时任务,在使用人数较少的时候来更新索引,
112 0
sphinx(五)php执行sphinx更新索引rotate命令
|
搜索推荐 PHP 定位技术
WordPress纯PHP代码实现记录搜索引擎蜘蛛爬行记录
在新站或网站收录有问题时,可能需要持续关注搜索引擎蜘蛛的抓取情况。每次打开服务器端访问日志查看非常麻烦,特别是当日志文件比较大时更是不便。最好的办法就是在线直接打开看蜘蛛爬行记录。为此,我们可以免插件使用纯PHP代码来实现这个功能,以下是具体实现代码。
1958 0
|
PHP
php建立多层目录的函数
/** *根据路径path建立多级目录 *$dir目标目录 $mode权限,0700表示最高权限 */ function makedir( $dir , $mode = "0700" ) { if(strpos($dir , "/" )){ $dir_p...
638 0