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
打开网址 http://www.coreseek.cn/news/7/52/ 找到适合自己的操作系统的版本,比如我是Windows 那么我就可以下载 Coreseek Win32 通用版本 ,Linux 下可以下载源码包,自己编译安装。这里解释下为什么我们下载的程序叫Coreseek ,Coreseek 是基于Sphinx 开发的一款软件,对Sphinx 做了一些改动,在中文方面支持得比Sphinx 好,所以我们使用之。
下载完成后,将程序解压到你想解压的地方,比如我就想解压到E 盘根目录,之后修改目录名为Coreseek ,大功告成Coreseek 安装完成了,安装的目录是在E:/coreseek/ 。
5. 使用Sphinx
我要使用Sphinx 需要做以下几件事
1) 首先得有数据
2) 建立Sphinx 配置文件
3) 生成索引
4) 启动Sphinx
5) 使用之(调用api 或search.exe 程序进行查询)
第1 件:(导入数据)
我们建立测试所需要用到得数据库、表以及数据,篇幅有限,这些在附件中都有,下载后导入MySQL 即可。
第2 件:(建立配置文件)
接下来我们需要建立一个Sphinx 的配置文件 E:/coreseek/etc/mysql.conf ,将其内容改为下面这些:
source mysql
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass =
sql_db = test
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query = SELECT id,addtime,title,content FROM post
sql_attr_timestamp = addtime
}
index mysql
{
source = mysql
path = E:/coreseek/var/data/mysql
charset_dictpath = E:/coreseek/etc/
charset_type = zh_cn.utf-8
}
searchd
{
listen = 9312
max_matches = 1000
pid_file = E:/coreseek/var/log/searchd_mysql.pid
log = E:/coreseek/var/log/searchd_mysql.log
query_log = E:/coreseek/var/log/query_mysql.log
}
先讲下这个配置文件中每项的含义。
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 就是时间戳类型。
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
searchd{} sphinx 守护进程配置
listen 监听端口
max_matches 最大匹配数,也就是查找的数据再多也只返回这里设置的1000 条
pid_file pid 文件路径
log 全文检索日志
query_log 查询日志
好了,配置文件就这样,配置的参数还有很多,大家可以自己查文档。
第3 件:(生成索引)
开始 -> 运行 -> 输入cmd 回车,打开命令行工具
e:/coreseek/bin/indexer --config e:/coreseek/etc/mysql.conf --all
这一串东西其实就是调用indexer 程序来生成所有索引
如果只想对某个数据源进行索引,则可以这样:e:/coreseek/bin/indexer --config e:/coreseek/etc/mysql.conf 索引名称(索引名称指配置文件中所定义的)
--config,--all 这些都是indexer 程序的参数,想了解更多参数的朋友可以查看文档
运行命令后如果你没看到FATAL,ERROR 这些东西,那么索引文件就算生成成功了,比如我看到得就是
……… 省略………
using config file 'e:/coreseek/etc/mysql.conf'...
indexing index 'mysql'...
collected 4 docs, 0.0 MB
……… 省略………
第4 件:(启动Sphinx )
同样命令行下
e:/coreseek/bin/searchd --config e:/coreseek/etc/mysql.conf
运行后提示了一大堆东西
using config file 'e:/coreseek/etc/mysql.conf'...
listening on all interfaces, port=9312
accepting connections
不用管这些鸟文是啥意思,反正Sphinx 是启动好了。
现在有一串鸟文的这个命令行是不能关的,因为关了Sphinx 也就关了,如果觉得这样不爽,可以将Sphinx 安装成系统服务,在后台运行。
安装系统服务只需在命令行中输入以下命令
e:/coreseek/bin/searchd --config e:/coreseek/etc/mysql.conf --install
安装之后记得启动这个服务,不会启动那我没法,自己google 。
第5 步:(使用Sphinx )
在web 根目录下建立一个search 目录(当然不在根目录也行,同样目录名也可以随取),复制E:/coreseek/api/ sphinxapi.php 文件到search 目录(sphinxapi.php 这个是sphinx 官方提供的api ),开始php 程序的编写。
在search 目录建立一个文件,名字叫啥都行,我管它叫index.php ,其内容如下
<?php
include 'sphinxapi.php'; // 加载Sphinx API
$sc = new SphinxClient(); // 实例化Api
$sc->setServer('localhost', 9312); // 设置服务端,第一个参数sphinx 服务器地址,第二个sphinx 监听端口
$res = $sc->query('sphinx', 'mysql'); // 执行查询, 第一个参数查询的关键字,第二个查询的索引名称,mysql 索引名称(这个也是在配置文件中定义的),多个索引名称以, 分开,也可以用* 表示所有索引。
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 从而得到我们想要的数据。
查询结果中键值分别表示
2 唯一主键
weight 权重
attrs sql_attr_* 中配置
至此,搜索引擎算是完成一大半了,剩下的大家可以自行完成。
比如:
<?php
$ids = array_keys($res['matches']); // 获取主键
$ids = join(',', $ids);
$query = mysql_query("SELECT * FROM post WHERE id IN ({$ids})");
while($row = mysql_fetch_assoc($query)) {
.....
}
Sphinx 的更多配置,程序的参数等,大家可以查看 Sphinx 的文档 。