本文主要是介绍Sphinx实验手册,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Sphinx实验手册
Sphinx+linux+apache+mysql+php+coreseek
环境准备:
源代码编译的LAMP环境
Centos 5.5 Linux版本
Mysql-5.1 mysql版本
Apache-2.2.9 apache版本
Php-5.2.6 php版本
Sphinx安装与运行测试
(1)、下载Sphinx
从sphinx官网上找到sphinx的安装源码,我们下的是0.9.9-release版。
下载地址:http://www.sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz
如果你的linux能联网的话,用wget命令直接下载.
Wget http://www.sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz
解压:tar-zxvfsphinx-0.9.9.tar.gz
(2)、编译安装
进入到sphinx的源码文件夹里,运行下列命令就可以安装sphinx了:
cd /lamp/sphinx-0.9.9
./configure --prefix=/usr/local/sphinx --with-mysql=/usr/local/mysql
make && make install
Sphinx中重要的三个命令,(Sphinx安装的bin目录下)
Indexer 创建索引命令。Searchd 启动进程命令。Search 命令行搜索命令。
(3)、准备mysql数据
我们需要一些数据,这里我们用安装mysql自带的test库进行测试
准备一个post贴子表,其中该表的字段如下:
Create table post(
Id int unsigned auto_increment primary key,
Titlevarchar(200),
Content text);
(4)、进入mysql中查看并添加的数据
/usr/local/mysql/bin/mysql-uroot –p123 test
向post贴子表中导入数据:
mysql> insert into post(title,content)values ('兄弟连','感谢LAMP兄弟连的广大会员,感谢一直以来对兄弟连的关注与支持');
(5)、配置sphinx.conf配置文件。
进入到sphinx的etc目录找到配置文件
cd /usr/local/sphinx/etc
我们需要备份一下配置文件,防止改错不好处理。
cp sphinx.conf.dist sphinx.conf
进入配置文件
vim sphinx.conf
配置文件的格式:
#################################################################
主数据源:
source main{
}
增量数据源:
source delta:main{
}
主数据索引:
index main{
}
增量数据索引:
index delta:main{
}
分布式索引:
index dist1{
}
索引器:
indexer{
}
服务进程:
searchd{
}
#################################################################
sphinx.conf的基本配置:
数据源 src是名字可以自己指定,即主数据源
source src1
{
type = mysql #数据库类型
sql_host =localhost # MySQL主机IP
sql_user = root # MySQL用户名
sql_pass = 123 # MySQL密码
sql_db = test # MySQL数据库
sql_port =3306 # MySQL端口
sql_sock =/tmp/mysql.sock #如果是linux下需要开启,指定sock文件
sql_query_pre =SET NAMES UTF8 # MySQL检索编码
sql_query_pre =SET SESSION query_cache_type=OFF #关闭缓存
sql_query = \ #获取数据的SQL语句
SELECT id, title,content FROM post
#sql_attr_uint =group_id #对排序字段进行注释
#sql_attr_timestamp= date_added #对排序字段进行注释
sql_query_info = SELECT * FROM post WHERE id=$id
} #这行不需要修改
sourcesrclthrottled:srcl #继承主数据源
主数据源索引:
index text1
{
source = src1 #索引源声明
charset_type =utf-8 #数据编码(设置成utf8)
charset_table = #上面指定了utf-8,这里需要开启
}
增量索引
indextestlstemmed:test1 #先进行注释
index distl #分布式也注释掉
索引器设置
indexer
{
mem_limit = 256M # 内存大小限制 默认是 32M, 推荐为 256M
} #其他用默认即可
sphinx服务进程searchd的相关配置
searchd {
} #全部用默认的就可以了
如果是本地测试,使用默认就可以,如果是多个服务器测试需要指定监听的ip即可
#Sphinx配置文件结束
(6)、创建索引
Sphinx的配置文件配置完成,数据也导进去了,接下来就用下面命令来创建索引:
创建索引命令:indexer
-c 指定配置文件
--all 对所有索引重新编制索引
--rotate 用于轮换索引,主要是再不停止服务的时候,增加索引
--merge 合并索引
/usr/local/sphinx/bin/indexer-c /usr/local/sphinx/etc/sphinx.conf --all
创建索引时报了一个这样的错误:/usr/local/sphinx/bin/indexer: error while loading shared libraries:libmysqlclient.so.16: cannot open shared object file: No such file or directory
可以用下面方法解决:
locate libmysqlclient 运行该命令找到关于libmysqlclient.so.16的文件
然后把该文件的一个连接复制到在环境变量的文件夹/usr/lib/下
cp /usr/local/mysql/lib/mysql/libmysqlclient.so.16 /usr/lib/libmysqlclient.so.16
再次运行创建索引命令就能完成索引的创建了
出现这样的提示就表示创建成功
(7)、测试
检查数据命令:search
/usr/local/sphinx/bin/search-c /usr/local/sphinx/etc/sphinx.conf test
可以看到将数据中含有test关键字的数据查询出来,包括文档id,权重,属性值等
我们搜索下中文看下。
/usr/local/sphinx/bin/search-c /usr/local/sphinx/etc/sphinx.conf '兄弟连'
找不到数据,为什么?
Coreseek-带有中文分词的Sphinx
Coreseek介绍:
Sphinx默认不支持中文索引及检索,基于Sphinx开发了Coreseek 全文检索服务器,Coreseek应该是现在用的最多的Sphinx中文全文检索,它提供了为Sphinx设计的中文分词包LibMMSeg包含mmseg中文分词
(1)、下载中文分词包
http://www.coreseek.cn 到官网去下载Coreseek相应的版本
(2)、解压安装
cd /lamp
tar -zxvf coreseek-3.2.14.tar.gz
进入到mmseg所在文件夹,先安装中文分词mmseg
cd /lamp/coreseek-3.2.14/mmseg-3.2.14/
./configure --prefix=/usr/local/mmseg
编译过程中报了一个config.status:error: cannot find input file: src/Makefile.in
这个的错误,然后运行下列指令再次编译就能通过了:
automake
然后再进行编译和安装:
make && make install
然后运行mmseg,就能输入安装成功的信息了:
/usr/local/mmseg/bin/mmseg
出现下列信息,就证明mmseg中文分词已经安装好了。
接下来,我们要把Sphinx和mmseg结合起来
(1)、检测安装
进入coreseek目录,进行安装
cd /lamp/coreseek-3.2.14/csft-3.2.14/
make &&make install
(2)、配置带有中文分词的sphinx配置文件
配置文件和上面的步骤一样,只不过是在coreseek中,有几个地方需要注意。
注意:coreseek中得配置文件也是csft.conf,而不是sphinx.conf
cd /usr/local/coreseek/etc
cp sphinx.conf.dist csft.conf
vim csft.conf
其他地方都一样,对照下面不一样的地方修改
index test1
{
#stopwords = G:\data\stopwords.txt
#wordforms =G:\data\wordforms.txt
#exceptions =/data/exceptions.txt
#charset_type =sbcs
添加下面这两行,意思是把中文分词加入到配置文件中
charset_dictpath = /usr/local/mmseg/etc/ #你安装mmseg的目录
}
(3)、生成索引并测试
创建索引
/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/csft.conf --all
再次测试搜索中文
/usr/local/coreseek/bin/search[-a] -c /usr/local/coreseek/etc/csft.conf '兄弟连'
注意:如果你设置的coreseek配置文件为csft.conf,则inder、search和searchd时不用带上-c/usr/local/coreseek/etc/csft.conf,因为默认就是去寻找这个文件.
我们在linux下Sphinx,中文分词已经安装完成了,并测试成功
如何用PHP去使用Sphinx技术
在这篇中我们使用 php 程序操作 Sphinx做个小的站内搜素引擎
Sphinx集成到PHP程序中,有两种方式:
1.Sphinx php模块
2.Sphinxapi类
我们要使用 Sphinx需要做以下几件事:
1、首先得有数据
2、建立Sphinx配置文件
3、生成索引
4、启动Searchd服务进程,并开户端口9312
5、用PHP客户程序去连接Sphinx服务
一、启用sphinx服务
想要在程序中使用Sphinx必须开启Sphinx服务
启动进程命令: searchd
-c #指定配置文件
--stop #是停止服务
--pidfile #用来显式指定一个 PID 文件
-p #指定端口
/usr/local/coreseek/bin/searchd-c /usr/local/coreseek/etc/csft.conf
注意:这里启动的服务是searchd,不是search
Sphinx默认的端口是9312端口
如果出现这个问题:
说明端口已经被占用了,解决的办法是:netstat --tunpl | grep 9312找出进程 ID,
kill -9进程id,再开启就可以了
二、用PHP连接使用Sphinx程序
(1)全PHP加载Sphinx模块
wget http://pecl.php.net/get/sphinx-1.1.0.tgz
tar zxf sphinx-1.1.0.tgz
cd /www/soft/sphinx-1.1.0
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config
提示出错:
checking for libsphinxclient headers in default path... not found
configure: error: Cannot find libsphinxclient headers
找了下libsphinxclient,在/www/soft/csft-3.2.13/api/libsphinxclient,之前安装的是coreseek3.2.13版
cdlibsphinxclient/
./configure
make && make install
安装完libsphinxclient,继续安装sphinx扩展
cd/www/soft/sphinx-1.1.0
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/
看到sphinx.so
vi /usr/local/webserver/php/etc/php.ini
加入extension = sphinx.so
/usr/local/apache2/bin/apachectlrestart
测试Sphinx模块,http://192.168.10.1/phpinfo.php
(2)、使用API类连接Sphinx程序
需要到coreseek解压包中找到sphinxapi.php文件,放到程序目录下
cp /lamp/coreseek-3.2.14/csft-3.2.14/api/sphinxapi.php/usr/local/apache2/htdocs/
include'sphinxapi.php';
//加载Sphinx API
$sphinx = newSphinxClient();
#创建sphinx对象
$sphinx->SetServer("localhost",9312);
#建立连接,第一个参数sphinx服务器地址,第二个sphinx监听端口
$result =$sphinx->query($keyword,"*");
#执行查询,第一个参数查询的关键字,第二个查询的索引名称,多个索引名称用,分开,也可以用*表示全部索引,其中包括增量索引
print_r($result);
#打印结果
找到下面这一段,是我匹配的数据
[matches] =>Array ( //匹配的结果
[6] => Array
[weight] => 4
[attrs] => Array
[group_id] => 1
[date_added] => 1319127367
#一个多维的数组,下标[6]是你匹配包含关键字的文档id,id对应的数组,[weight]是权重,[attrs]是属性,我们在配置文件中指定的
这段也是我们需要的数据
[total] => 2
#此查询在服务器检索所得的匹配文档总数
[total_found]=> 2
#索引中匹配文档的总数
[time] => 0.009
#这个是我们这次查询所用的时间
[words] =>Array (
[兄弟] =>Array
[docs] => 2 在文档中出现多少次 (content 字段中)
[hits] => 6 一共出现多少次
[连] =>Array
[docs] => 2
[hits] => 6
(3)、取得数据摘要并高亮显示
Matches中就是我们匹配的结果,但是仿佛不是我们想要的数据,比如 titile,content字段的内容就没有匹配出来,根据官方的说明是 Sphinx 并没有连接到MySQL去取数据,只是根据它自己的索引内容进行计算,因此如果想用 Sphinx 提供的API 去取得我们想要的数据,还必须以查询的结果为依据,再次查询 MySQL从而得到我们想要的数据
比如:
$mysqli = newmysqli("localhost","root","password","test");
$ids=join(',',array_keys($result['matches'])); 要把需要的id取出来。
$sql="selecttitle,content from post where id in({$ids})”;
$result=$mysqli->query($sql);
while($row=$result->fetch_row()){
#循环体开始解析看下结果.
下面我们在输出结果的时候需要生成摘要,高亮(就是和百度一样,关键字飘红)我们需要用到 buildExcerpts 这个函数,(php 手册中)语法格式:
public arraySphinxClient::buildExcerpts ( array $docs , string $index , string
$words [, array$opts ])
#返回的是一个数组,一共有四个参数
#第一个参数是从数据库中查询的结果集
#第二个参数是索引的名字
#第三个参数是要高亮显示的关键字
#第四个参数是显示的字 格式化
$opts = array(
#格式化摘要,高亮字体设置
#在匹配关键字之前插入的字符串,默认是<b>
"before_match" => "<span style='font-weight:bold;color:red'>",
#在匹配关键字之后插入的字符串,默认是</b>
"after_match" => "</span>",
#在摘要段落之前插入的字符串默认 „
"chunk_separator"=> " ... ",
);
$res=$sphinx->buildExcerpts($row,"index",$keyword,$opts);
echo"<fontsize=4>".$res[0]."</font></a></br>"; 标题
echo"<fontsize=2>".$res[1]."</font></br>"; 摘要
echo$res[2]."</p>"; 添加时间
}
#循环体结束
到这里呢,我们用php程序调用sphinxapi实现了高亮摘要功能
三、匹配模式
匹配模式:SetMatchMode(设置匹配模式)
原型:function SetMatchMode ( $mode )
SPH_MATCH_ALL 匹配所有查询词(默认模式).
SPH_MATCH_ANY 匹配查询词中的任意一个.
SPH_MATCH_PHRASE 将整个查询看作一个词组,要求按顺序完整匹配.
SPH_MATCH_BOOLEAN 将查询看作一个布尔表达式.
SPH_MATCH_EXTENDED将查询看作一个 Sphinx 内部查询语言的表达式.
SPH_MATCH_FULLSCAN使用完全扫描,忽略查询词汇.
SPH_MATCH_EXTENDED2类似 SPH_MATCH_EXTENDED ,并支持评分和权重
四、Sphinx实时索引
数据库中的数据很大,然后我有些新的数据后来加入到数据库中,也希望能够检索到,全部重新建立索引很消耗资源,这样需要用到“主索引+增量索引”的思路来解决,这个模式实现的基本原理是设置两个数据源和两个索引。
1、创建一个计数器
一个简单的实现是,在数据库中增加一个计数表,记录将文档集分为两个部分的文档 ID,每次重新构建主索引时,更新这个表
先在 mysql 中插入一个计数表
CREATE TABLEsph_counter( counter_id INTEGER PRIMARY KEY NOT NULL, max_doc_id INTEGER NOT NULL);
2、再次修改配置文件
主数据源,继承数据源,主索引,继承索引。(继承索引也就是增量索引)。
主数据源里面:我们需要把欲查询语句改成下面的语句:
Vi/usr/local/coreseek/etc/csft.conf
Source main{
把sql_query_pre的改成下面的语句
sql_query_pre =REPLACE INTO sph_counter SELECT 1, MAX(id) FROM post
sql_query= \
SELECT id,title,content FROM post \
WHERE id<=(SELECTmax_doc_id FROM sph_counter WHERE counter_id=1)
}
继承数据源:
source delta :main
{
sql_query_pre =SET NAMES utf8
sql_query
= \
SELECT id,title,content FROM post \
WHERE id>(SELECTmax_doc_id FROM sph_counter WHERE counter_id=1)
}
主索引:
把名字该成想对应的
Index main {
source = main
path = /usr/local/coreseek/var/data/main
}
继承索引(也是增量索引)
index delta:main
{
source= delta
path= /usr/local/coreseek/var/data/delta
}
剩下的基本不用改变
注意:如果你增量索引的source 配置中只有 id,content 三项
而主索引的 source 配置中有 id, title,content四项,合并的时候会报属性数量不匹配,如:
Delta:sql_query =SELECT id, title,content FROM post
Main:sql_query=SELECTid,title,date,content FROM post
3、测试增量索引+主索引
如果想测试增量索引是否成功,往数据库表中插入数据,查找是否能够检索到,这个时候检索应该为空,然后,单独重建增量索引
/usr/local/coreseek/bin/indexer-c /usr/local/coreseek/etc/csft.conf delta
查看是否将新的记录进行了索引,如果成功
此时,再用/usr/local/coreseek/bin/search工具来检索,能够看到,在主索引中检索到的结果为 0,而在增量中检索到结果。当然,前提条件是,检索的词,只在后来插入的数据中存在
4、实时更新索引
我们需要建立两个脚本,还要用到计划任务
建立一个主索引和增量索引的脚本
main.sh delta.sh
在增量索引中写下delta.sh
#!/bin/bash
#delta.sh
/usr/local/coreseek/bin/indexerdelta >>/usr/local/coreseek/var/log/delta.log
主索引中写下:main.sh意思就是合并索引
#!/bin/bash
#main.sh
/usr/local/coreseek/bin/indexer main >>/usr/local/coreseek/var/log/merge.log
最后,我们需要脚本能够自动运行,以实现增量索引每5分钟重新建立,和主索引只在凌晨2:30时重新建立.
脚本写好了,我们需要建立计划任务
crontab -e
*/10 * * * * /usr/local/coreseek/etc/delta.sh
30 2 * * * /usr/local/coreseek/etc/main.sh
第一条是表示每5分钟运行
第二条是表示每天的凌晨2:30分运行
脚本权限:
chmod a+x delta.sh
chmod a+x main.sh
要验证的话,我们可以查看日志文件
五、分布式索引
分布式是为了改善查询延迟问题和提高多服务器、多 CPU 或多核环境下的吞吐率,对于大量数据(即十亿级的记录数和 TB 级的文本量)上的搜索应用来说是很关键的
分布式思想:对数据进行水平分区(HP,Horizontally partition),然后并行处理,
当searchd收到一个对分布式索引的查询时,它做如下操作
1. 连接到远程代理.
2. 执行查询.
3. 对本地索引进行查询.
4. 接收来自远程代理的搜索结果.
5. 将所有结果合并,删除重复项.
6. 将合并后的结果返回给客户端.
index dist
{
type = distributed
local = chunk1
agent =localhost:9312:chunk2 本地
agent =192.168.100.2:9312:chunk3 远程
agent =192.168.100.3:9312:chunk4 远程
}
Sphinx我们已经基本讲完,主要讲解了包括 Sphinx、中文分词、高亮、摘要、匹配、增量索引、实时索引和分布式索引等方面的知识.
六.PHP代码实例:
Viindex.php
<html>
<head>
<metahttp-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<h1>简单PHP搜索测试</h1>
<form action="find.php"method=post>
请输入搜索关键字:<input type="text"name="word"><br>
<input type="submit" name="submit"><br>
</form>
</body>
</html>
Vi find.php
<html>
<head>
<metahttp-equiv="content-type" content="text/html; charset=utf-8">
<title>Find</title>
</head>
<body>
<h1 id='top'>查询输出页面</h1>
<?php
$keyword=$_POST['word'];
$sphinx=new SphinxClient();
$sphinx->SetServer("localhost",9312);
$sphinx->SetMatchMode(SPH_MATCH_ANY);
//$sphinx->setLimits(0,0);
$result=$sphinx->query("$keyword","*");
//echo "<pre>";
//print_r($result);
//echo "</pre>";
$ids=join(",",array_keys($result['matches']));
mysql_connect("localhost","root","123");
mysql_select_db("test");
$sql="select * from post where idin({$ids})";
mysql_query("set namesutf8");
$rst=mysql_query($sql);
$opts=array(
"before_match"=>"<buttonstyle='font-weight:bold;color:#f00'>",
"after_match"=>"</button>"
);
while($row=mysql_fetch_assoc($rst)){
$rst2=$sphinx->buildExcerpts($row,"main",$keyword,$opts);
echo "第{$rst2[0]}篇贴子<br>";
echo "标题: {$rst2[1]}<br>";
echo "内容: {$rst2[2]}<br>";
echo "<hr>";
}
?>
<body>
<html>
这篇关于Sphinx实验手册的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!