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/

./configure --prefix=/usr/local/coreseek --with-mysql=/usr/local/mysql --with-mmseg=/usr/local/mmseg --with-mmseg-includes=/usr/local/mmseg/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg/lib/

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_type        = zh_cn.utf-8

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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值