Sphinx+php实战

2017/10/20
原创+网上抄袭
全文检索实战
用的coreseek 基于sphinx 为了中文分词
这个整个流程下来,感觉就是为php和mysql开发用的。
耦合程度高。方便继承,反正就是phper用起来很爽

安装准备

yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2-devel expat-devel
#或
apt-get install make gcc g++ automake libtool mysql-client libmysqlclient15-dev libxml2-dev libexpat1-dev

先安装mmseg分词 coreseek搜索

wget http://www.coreseek.cn/uploads/csft/4.0/coreseek-4.1-beta.tar.gz  
tar zxvf coreseek-4.1-beta.tar.gz  
  
cd coreseek-4.1-beta  
cd mmseg-3.2.14  
./bootstrap  
./configure --prefix=/usr/local/mmseg3  
make && make install  

cd csft-4.1
sh buildconf.sh   如果报错请查找原因
./configure --prefix=/usr/local/coreseek  --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql
make && make install 

如果报错
一开始以为libiconv的问题,又重装了几次还是一样,最后终于找着办法了
 编辑:
 ./src/MakeFile文件
 将
 LIBS = -lm -lexpat -L/usr/local/lib
 改成
 LIBS = -lm -lexpat -liconv -L/usr/local/lib
 
cd testpack
cat var/test/test.xml

/usr/local/mmseg3/bin/mmseg -d /usr/local/mmseg3/etc var/test/test.xml
/usr/local/coreseek/bin/indexer -c ./etc/csft.conf --all
/usr/local/coreseek/bin/search -c ./etc/csft.conf 网络搜索

到现在已经完成安装和测试了。接下来配合mysql实现  
 

coreseek与mysql的配置

进入etc目录,拷贝配置文件, cp  sphinx-min.conf.dist  sphinx.conf  (这里不拷贝sphinx.conf.dist ,因为这文件只是比前者多了一堆注释)
cp /testpack/etc/csft_mysql.conf /usr/local/coreseek/etc/
然后修改 配置coreseek数据库源文件





# 源定义
source news_src
{
	  type                                    = mysql #####数据源类型
	  sql_host                                = localhost ######mysql主机
	  sql_user                                = root ########mysql用户名
	  sql_pass                                = 123456 ############mysql密码
	  sql_db                                  = test #########mysql数据库名
	  sql_port                                = 3306  ###########mysql端口
	  sql_query_pre   = SET NAMES UTF8  ###mysql检索编码,特别要注意这点,很多人中文检索不到是数据库的编码是GBK或其他非UTF8
	  sql_query                               = \
			  SELECT id, catid, keywords, title, description \
			  FROM v9_news ####### 获取数据的sql
	  sql_attr_uint                   = id ######## 无符号整数属性
	  sql_attr_uint                   = catid  ###让客户端SetFilter调用

	  sql_query_info          = SELECT * FROM v9_news WHERE id=$id ######### 用于命令界面端(CLI)调用的测试
}

####### 索引定义 ##########
index news
{
source = news_src ####声明索引源
path                    = /usr/local/coreseek/var/data/news #######索引文件存放路径及索引的文件名
docinfo = extern ##### 文档信息存储方式
mlock = 0 ###缓存数据内存锁定
morphology = none  #### 形态学(对中文无效)
min_word_len = 1  #### 索引的词最小长度
html_strip            = 0 
charset_dictpath     = /usr/local/mmseg3/etc/  #BSD、Linux环境下设置,/符号结尾 分词库路径定义 
charset_type        = zh_cn.utf-8 #####数据编码
}

######### 全局index定义 ##############
indexer
{
mem_limit = 128M ####### 内存限制
}

###### searchd服务定义 ###
searchd
{
# listen              = 9312   ### 监听端口,在此版本开始,官方已在IANA获得正式授权的9312端口,以前版本默认的是3312
log = /usr/local/coreseek/var/log/searchd.log
query_log = /usr/local/coreseek/var/log/query.log ### 客户端查询日志,笔者注:若欲对一些关键词进行统计,可以分析此日志文件
read_timeout = 5 ## 请求超时
max_children = 30 ### 同时可执行的最大searchd 进程数
pid_file = /usr/local/coreseek/var/log/searchd.pid #######进程ID文件
max_matches = 1000  ### 查询结果的最大返回数
seamless_rotate = 1  ### 是否支持无缝切换,做增量索引时通常需要
}

# 注 配置文件中源和索引都可以针对不同的数据库或不同的查询条件配置多个 

# 注 如果联查直接join就可以了。





/usr/local/coreseek/bin/searchd -c /usr/local/coreseek/etc/csft_mysql.conf 启动服务  --stop停止服务

/usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/csft_mysql.conf --all --rotate 创建索引

/usr/local/coreseek/bin/search -c /usr/local/coreseek/etc/csft_mysql.conf 你好 //搜索

然后在去到安装的源目录 testpack/api/test.php即可看到信息

/usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/csft_mysql.conf test ### 建立索引文件的命令  索引名称
这个起名字有利于不同的表查询 指定不同的索引


将执行索引加入到Linux计划任务中,定时执行更新,合并,整体索引 

为了方便,我们将执行整体索引,增量索引,合并索引分别写到3个shell文件中

复制代码

cd /usr/local/coreseek/sh
vi all.sh
/usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/csft_mysql.conf --all --rotate

vi delta.sh
/usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/csft_mysql.conf delta --rotate 

然后,执行crontab -e 写入如下内容

*/1 * * * * /bin/sh /usr/local/coreseek/sh/delta.sh >/dev/null 2>&1 ##每1分钟执行增量索引
*/5 * * * * /bin/sh /usr/local/coreseek/sh/merge.sh >/dev/null 2>&1 ##每5分钟合并索引



如果加上分页就很简单
比如:
if (!empty($_GET) && !empty($_GET['p'])) 
{
	$p = !intval(trim($_GET['p'])) == 0 ? intval(trim($_GET['p'])) - 1 : 0;
	$p = $p * 20;
	// 我在sed.conf 设置了最大返回结果数1000。但是我在生成页码的时候最多生成20页,我想能满足大部分搜索需求了。
	// 以下语句表示从P参数偏移开始每次返回20条。
	$cl->setLimits($p, 20);
} else 
{
	$cl->setLimits(0, 20);
}

如果要生成分类的页码那?就更简单了。比如以thinkphp为例
$count=$result['total'];//sphinx搜索总数
$Page = new Page($count,$PageSize);
$this->page=$Page->show();


coreseek属性过滤

比如要设置属性过滤那?可以这样  $cl->setFilter


属性列表

//筛选cat_id=2  
$cl->SetFilter("cat_id",array(2));  
//仅在id为1、3、7的子论坛中搜索  
$cl->SetFilter("forum_id",array(1,3,7));  
  
//范围筛选  
//筛选发布时间为今天,参数为int时间戳  
$cl->SetFilterRange("starttime",123,124);  
//筛选价格  
$cl->SetFilterRange("price",10.0,99.9);  
  
// 分组  
//按照item_id分组,并且按照order desc排序  
$cl->SetGroupBy("item_id",SPH_GROUP_ATTR,"order desc");  
  
//排序模式  
//按照price desc排序  
$cl->SetSortMode(SPH_SORT_ATTR_DESC,"price");  
 注意:会被SetGroupBy中的排序覆盖  
  
// 匹配查询词中的任意一个  
$cl->SetMatchMode ( SPH_MATCH_ANY );  
SPH_MATCH_ALL, 匹配所有查询词(默认模式);  
SPH_MATCH_ANY, 匹配查询词中的任意一个;  
SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配;  
SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式 (参见 第 5.2 节 “布尔查询语法”);  
SPH_MATCH_EXTENDED, 将查询看作一个CoreSeek/Sphinx内部查询语言的表达式 (参见 第 5.3 节 “扩展查询语法”). 从版本Coreseek 3/Sphinx 0.9.9开始, 这个选项被选项SPH_MATCH_EXTENDED2代替,它提供了更多功能和更佳的性能。保留这个选项是为了与遗留的旧代码兼容——这样即使 Sphinx及其组件包括API升级的时候,旧的应用程序代码还能够继续工作。  
SPH_MATCH_EXTENDED2, 使用第二版的“扩展匹配模式”对查询进行匹配.  
SPH_MATCH_FULLSCAN, 强制使用下文所述的“完整扫描”模式来对查询进行匹配。注意,在此模式下,所有的查询词都被忽略,尽管过滤器、过滤器范围以及分组仍然起作用,但任何文本匹配都不会发生.






自定义demo

<?php

<?php
require ( "sphinxapi.php" );
$keyword = trim($_POST['keyword']); 
$cl = new SphinxClient ();

$cl->SetServer('118.190.65.33', 9312);
$cl->SetConnectTimeout(3);
$cl->SetArrayResult(true);
$cl->SetSortMode(SPH_SORT_RELEVANCE);
$cl->SetMatchMode(SPH_MATCH_ALL);//类似like

$cl->SetSortMode(SPH_SORT_EXTENDED, "id DESC"); //排序 与下面的权重只能使用一种模式


//加权重
$cl->SetMatchMode ( SPH_MATCH_EXTENDED );//设置模式
$cl->SetRankingMode ( SPH_RANK_PROXIMITY );//设置评分模式
$cl->SetFieldWeights (array('name'=>2,'bname'=>1));//设置字段的权重,如果area命中,那么权重算2
$cl->SetSortMode ('SPH_SORT_EXPR','@weight');//按照权重排序

//设置字段搜索
//$cl->SetFilter( "textbook_id", array ( 8 ) );
//$cl->SetFilter( "bid", array ( 52 ) );
//$cl->SetFilter( "id", array ( 7 ) );

if (!empty($_POST) && !empty($_POST['p'])) {
	$p = !intval(trim($_POST['p'])) == 0 ? intval(trim($_POST['p'])) - 1 : 0;
	$p = $p * 20;
	// 我在sed.conf 设置了最大返回结果数1000。但是我在生成页码的时候最多生成20页,我想能满足大部分搜索需求了。
	// 以下语句表示从P参数偏移开始每次返回20条。
	$cl->setLimits($p, 20, 1000);
} else {
    $cl->setLimits(0, 20, 1000);
}

$res = $cl->Query($keyword, "*"); //查找全部索引
print_r($res);

个人sphinx配置

#MySQL数据源配置,详情请查看:http://www.coreseek.cn/products-install/mysql/
#请先将var/test/documents.sql导入数据库,并配置好以下的MySQL用户密码数据库

#源定义
source mysql
{
    type                    = mysql

    sql_host                = localhost
    sql_user                = root
    sql_pass                = Jby&*2016
    sql_db                    = jingtongcloud
    sql_port                = 3306
    sql_query_pre            = SET NAMES utf8

    sql_query                = SELECT bb.id,bb.name as bname,biz_bj_resources.name,biz_bj_resources.id as bid,biz_bj_resources.textbook_id FROM bb LEFT JOIN biz_bj_resources ON biz_bj_resources.id = bb.id;
                                                              #sql_query第一列id需为整数
                                                              #title、content作为字符串/文本字段,被全文索引
    
    sql_attr_uint            = id
    sql_attr_uint            = bid
    sql_attr_uint            = textbook_id

    sql_attr_timestamp        = date_added #从SQL读取到的值必须为整数,作为时间属性

    sql_query_info_pre      = SET NAMES utf8                                        #命令行查询时,设置正确的字符集
    sql_query_info            = SELECT bb.id,bb.name as bname,biz_bj_resources.name,biz_bj_resources.id as bid,biz_bj_resources.textbook_id FROM bb LEFT JOIN biz_bj_resources ON biz_bj_resources.id = bb.id WHERE bb.id=$id; #命令行查询时,从数据库读取原始数据信息
}

#index定义
index mysql
{
    source            = mysql             #对应的source名称
    path            = /usr/local/coreseek/var/data/mysql #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    docinfo            = extern
    mlock            = 0
    morphology        = none
    min_word_len        = 1
    html_strip                = 0

    #中文分词配置,详情请查看:http://www.coreseek.cn/products-install/coreseek_mmseg/
    charset_dictpath = /usr/local/mmseg3/etc/ #BSD、Linux环境下设置,/符号结尾
    #charset_dictpath = etc/                             #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
    charset_type        = zh_cn.utf-8
}

#全局index定义
indexer
{
    mem_limit            = 128M
}

#searchd服务定义
searchd
{
    listen                  =   9312
    read_timeout        = 5
    max_children        = 30
    max_matches            = 1000
    seamless_rotate        = 0
    preopen_indexes        = 0
    unlink_old            = 1
    pid_file = /usr/local/coreseek/var/log/searchd_mysql.pid  #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    log = /usr/local/coreseek/var/log/searchd_mysql.log        #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    query_log = /usr/local/coreseek/var/log/query_mysql.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
    binlog_path =                                #关闭binlog日志
}


个人随笔

安静的等待,你若盛开,蝴蝶自来

承接高质量 网站开发 app开发 如有需要请点击About联系

@承鹏辉