Sphinx全文检索引擎的排序

Sphinx不能严格按照字段排序的小问题

如果不想使用权重,只希望严格按照时间、主键等排序,而匹配模式(Matching modes)又为非SPH_MATCH_BOOLEAN时(比较常用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索结果在某一页中的排序会不太准确。例如:按照UNIX时间戳倒序排序,0,20为第一页,20,40为第二页,第一页的最小时间戳一定会大于第二页的最大时间戳,但是,第一页中的0,20条记录却不会严格按照时间戳排序,第二页亦是如此。因此,如果需要精确排序,用户翻到搜索结果的某一页,就需要对Sphinx在某一搜索结果页中的记录另行再排序。


具体实现的PHP代码如下:

首先,需要设置匹配模式为 $this->sphinx->SetMatchMode ( SPH_MATCH_BOOLEAN );

其次,设置排序规则:$this->sphinx->SetSortMode( SPH_SORT_EXTENDED, "pub_date DESC, @id DESC" );

最后,对分页之后返回的结果数组进行一个完全倒序,问题就可以解决了。




代码如下:


<?php

class CSearch{

public $sphinx; //sphinx对象指针

public $indexer; //在指定的索引中查询关键词

public $keyword; //查询关键词

public function CSearch(){
$this->sphinx = new CSphinx;
$this->sphinx->SetFieldWeights( array( "title" => 10, "content" => 5 ) );
$this->sphinx->SetMatchMode ( SPH_MATCH_BOOLEAN );
$this->sphinx->SetSortMode( SPH_SORT_EXTENDED, "pub_date DESC, @id DESC" );

}

/*
<summary>全文检索的查询入口</summary>
<params>
<keyword>将要检索的关键词</keyword>
<offset>返回的结果是从第$offset条开始输出的</offset>
<limit>返回的结果中,每页显示10条数据</limit>
<indexer>在指定的索引中检索关键词</indexer>
</params>
*/
public function query( $keyword, $offset = 0, $limit = 10, $indexer = "articles" ){
$returned = new stdClass;
$this->indexer = $indexer;
$this->keyword = $keyword;
$this->sphinx->SetLimits(  $offset, $limit );
$results = $this->sphinx->query( $keyword, $indexer ); //在指定的索引中检索关键词,并将符合条件的结果集放在$results变量中
$returned->total = $results["total"]; //符合条件的结果条数
$returned->time = $results["time"]; //查询所耗费的时间,单位:秒
$article_ids = array_keys( $results["matches"] ); //符合条件的文章ID数组
unset( $results ); //释放sphinx查询所创建的结果集对象
if( empty( $article_ids ) ){
$returned->data = Array();
return $returned;
}    
$data = $this->get_data( $article_ids ); //获取文章数据
$this->get_formated_data( $data, "content" ); //获取格式化之后的数据:产生文档片段(摘要)
$this->get_formated_data( $data, "title" ); //获取格式化之后的数据:产生文档片段(摘要)
$returned->data = array_reverse( $data );
return $returned;
}

/*
<summary>根据文章ID数组获取文章标题、作者、日期、guid和正文</summary>
<params>
<article_ids>文章ID数组</article_ids>
</params>
*/
public function get_data( $article_ids ){
return get_content_from_ids( $article_ids );
}

/*

*/
public function get_formated_data( &$data, $field = "content" ){
//$opts为包含其他可选的高亮参数的hash
$opts = Array();
$opts["single_passage"] = true; //是否仅抽取最佳的一个段落。布尔值。
$opts["before_match"] = '<span class="c_orange">'; //在匹配的关键字前面插入的字符
$opts["after_match"] = "</span>";
$opts["limit"] = 160; //摘要最多包含的符号(码点)数。整数
$contents = Array();
foreach( $data as $item ){
$item = trim( strip_tags( $item[$field] ) );
$contents[] = preg_replace( "/[\r\t\n]+/", "", $item );
}
$contents = $this->sphinx->buildExcerpts($contents, $this->indexer, $this->keyword, $opts );
foreach ($data as $k => &$v) {
$v[$field] = $contents[$k];
}
return $data;
}

}

?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值