@a5635268
2015-08-20T20:29:48.000000Z
字数 5902
阅读 1405
高效搜索
PHP性能优化
PHP可以通过三种途径来调用sphinx
首推此方法
cd coreseek-4.1/csft-4.1/api/libsphinxclient/
./configure --prefix=/usr/local/libsphinxclient
make && make install
# 处理configure报错
# 编译过程中报了一个config.status: error: cannot find input file: src/Makefile.in这个的错误,然后运行下列指令再次编译就能通过了:
# aclocal
# libtoolize --force
# automake --add-missing
# autoconf
# autoheader
# make clean
# 从新configure编译
# ./configure
# 下载http://pecl.php.net/package/sphinxapi
# 解压进入
/usr/bin/phpize #生成config
./configure --with-php-config=/usr/bin/php-config --with-sphinx=/usr/local/libsphinxclient
make && make install
#然后得到 Installing shared extensions: /usr/lib/php/modules/ 该目录就是php扩展所在的地方;
vim /etc/php.ini #搜索 extension=,然后再其附近加上sphinx.so
#重启Apache;在phpinfo()中找到sphinx就算成功;
Example1
<?php
$s = new SphinxClient;
$s->setServer("127.0.0.1", 9312);
$s->setMatchMode(SPH_MATCH_PHRASE);
$s->setMaxQueryTime(30);
$res = $s->query("简单",'main'); #[简单]关键字,[main]数据源source
$err = $s->GetLastError();
echo "<pre />";
print_r(array_keys($res['matches'])); #关键字所属的ID集合;
echo "<pre />";
die;
?>
Example2
注意,下文中被注释掉的部分仅仅作为参考;
<?php
header("Content-type: text/html; charset=utf-8");
$s = new SphinxClient();
$s->setServer("127.0.0.1", 9312);
$s->setMatchMode(SPH_MATCH_ANY);
/*
SPH_MATCH_ALL, 匹配所有查询词(默认模式);
SPH_MATCH_ANY, 匹配查询词中的任意一个;
SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配;
SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式
SPH_MATCH_EXTENDED, 将查询看作一个CoreSeek/Sphinx内部查询语言的表达式 . 从版本Coreseek 3/Sphinx 0.9.9开始, 这个选项被选项SPH_MATCH_EXTENDED2代替,它提供了更多功能和更佳的性能。保留这个选项是为了与遗留的旧代码兼容——这样即使Sphinx及其组件包括API升级的时候,旧的应用程序代码还能够继续工作。
SPH_MATCH_EXTENDED2, 使用第二版的“扩展匹配模式”对查询进行匹配.
SPH_MATCH_FULLSCAN, 强制使用下文所述的“完整扫描”模式来对查询进行匹配。注意,在此模式下,所有的查询词都被忽略,尽管过滤器、过滤器范围以及分组仍然起作用,但任何文本匹配都不会发生.
我们要关注的主要是SPH_MATCH_EXTENDED2扩展匹配模式,扩展匹配模式允许使用一些像mysql的条件语句
//设置扩展匹配模式
$sphinx->SetMatchMode ( "SPH_MATCH_EXTENDED2" );
//查询中使用条件语句,字段用@开头,搜索内容包含测试,toid等于1的邮件:
$result = $sphinx->query('@content (测试) & @toid =1', '*');
//用括号和&(与)、|、(或者)、-(非,即!=)设置更复杂的条件
$result = $sphinx->query('(@content (测试) & @subject =呃) | (@fromid -(100))', '*');
//更多语法请查看官方文档匹配模式的说明
*/
$s->setMaxQueryTime(10);//设置最大搜索时间
$s->SetArrayResult(true);//设为true,那Matches的key就是一个从0开始的数组索引,设为false,那key就是数据的id值;
$s->SetSelect ( "*" ); //设置返回信息的内容,等同于SQL
// $s->SetRankingMode(SPH_RANK_BM25);//设置评分模式,SPH_RANK_BM25可能使包含多个词的查询的结果质量下降。
//$s->SetSortMode(SPH_SORT_EXTENDED);
//$s->SetSortMode(SPH_SORT_EXTENDED,"from_id asc,id desc"); //设置匹配项的排序模式, SPH_SORT_EXTENDED按一种类似SQL的方式将列组合起来,升序或降序排列。
/*
SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)
SPH_SORT_ATTR_ASC 模式, 按属性升序排列(属性值越小的越是排在前面)
SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按相关度降序
SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排列。
SPH_SORT_EXPR 模式,按某个算术表达式排序
*/
// $s -> SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid'); //以fromid倒序排序,注意当再次使用SetSortMode会覆盖上一个排序
// $sphinx->SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid ASC, toid DESC, @id DESC'); //如果要使用多个字段排序可使用SPH_SORT_EXTENDED模式,@id是sphinx内置关键字,这里指emailid,至于为什么是emailid,自己思考一下
// $weights = array ('company_name' => 20);
// $s->SetFieldWeights($weights);//设置字段权重
$s->SetLimits ( 0, 10, 1000);//SetLimits (偏移量,匹配项数目,查询的结果集数默认1000,阀值达到后停止),匹配结果的偏移量,参数的意义依次为:起始位置,返回结果条数,最大匹配条数
//属性过滤,可过滤的属性必需在配置文件中设置sql_attr_ ,之前我们定义了这些
// sql_attr_uint = 'fromid';
// sql_attr_uint = 'toid';
// sql_attr_timestamp = 'sendtime';
//如果你想再次修改这些属性,配置完成后记得重新建立索引才能生效
//指定一些值
// $sphinx->SetFilter('fromid', array(1,2)); //fromid的值只能是1或者2
//和以上条件相反,可增加第三个参数
// $sphinx->SetFilter('fromid', array(1,2), false); //fromid的值不能是1或者2
//指定一个值的范围
// $sphinx->SetFilterRange('toid', 5, 200); //toid的值在5-200之间
//和以上条件相反,可增加第三个参数
// $sphinx->SetFilterRange('toid', 5, 200, false); //toid的值在5-200以外
//$s->SetFilter ( $attribute, $values, $exclude=false ); //设置属性过滤
//$s->SetGroupBy ( $attribute, $func, $groupsort="@group desc" );//设置分组的属性
$keyword = '小杨生煎';
$index = 'main'; //索引源是配置文件中的 index 类,如果有多个索引源可使用,号隔开:'email,diary' 或者使用'*'号代表全部索引源
$res = $s->query($keyword,$index);
echo "<pre />";
print_r($res);
echo "<pre />";
die;
$ids = implode(',',array_keys($res['matches']));
$conn=@mysql_connect('localhost','root','')||die('数据库链接失败!');
mysql_select_db('test');
mysql_query('set names utf8');
$sql = "select user_comment_id,user_recommend from data where user_comment_id in ({$ids})";
$result = mysql_query($sql);
$row = array();
$i = 0;
$opts = array(
'before_match' => "<font style='color:red;font-weight:bold;text-decoration:underline'>",
'after_match' => "</font>",
"limit" => 100, //摘要最多包含的符号数,默认256
"around" => 3, //每个关键词左右选取的词的数目,默认为5
);
while($f=mysql_fetch_assoc($result)){
$f = $s->BuildExcerpts ($f, 'main', $keyword, $opts);//执行高亮,这里索引名字千万不能用*
$row[$i]= $f;
$i++;
}
echo "<pre />";
print_r($row);
echo "<pre />";
die;
?>
直接进解压后的包里面找到sphinxapi.php,然后引入到文件中,其它操作都同上.虽然Coreseek官方教程中建议php使用直接include一个php文件进行操作,事实上php有独立的sphinx模块可以直接操作coreseek(coreseek就是sphinx!)已经进入了php的官方函数库,而且效率的提升不是一点点!但php模块依赖于libsphinxclient包。见上文;
SphinxSE是一个可以编译进MySQL 5.x版本的MySQL存储引擎,它利用了该版本MySQL的插件式体系结构。尽管被称作“存储引擎”,SphinxSE自身其实并不存储任何数据。它其实是一个允许MySQL服务器与searchd交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL之外。
SphinxSE的适用于:
要通过SphinxSE搜索,需要建立特殊的ENGINE=SPHINX的“搜索表”,然后使用SELECT语句从中检索,把全文查询放在WHERE子句中。
创建一张表t1
CREATE TABLE t1
(
id INTEGER UNSIGNED NOT NULL,
weight INTEGER NOT NULL,
query VARCHAR(3072) NOT NULL,
group_id INTEGER,
INDEX(query)
) ENGINE=SPHINX CONNECTION="sphinx://localhost:9312/test1";
搜索表前三列的类型必须是INTEGER,INTEGER和VARCHAR,这三列分别对应文档ID,匹配权值和搜索查询。查询列必须被索引,其他列必须无索引。列的名字会被忽略,所以可以任意命名,参数CONNECTION来指定用这个表搜索时的默认搜索主机、端口号和索引,语法格式:CONNECTION="sphinx://HOST:PORT/INDEXNAME"。
执行SQL语句 select d.id,d.title,d.content from t1 join documents as d on t1.id = d.id and t1.query = '研究生创业';
+----+--------------------+-----------------------+
| id | title | content |
+----+--------------------+-----------------------+
| 5 | 研究生的故事 | 研究生自主创业 |
+----+--------------------+-----------------------+
1 row in set (0.04 sec)
结果返回了我们想要的数据,可见利用SphinxSE可以仅仅在SQL语句上做很小的改动即可很方便的实现全文检索!
但是效率比起直接用官方的sphinx扩展模块来要远远不足。。。