基于xunsearch实现全文检索功能

发布时间:2020/11/13 作者:天马行空 阅读(857)

Xunsearch 是免费开源的专业全文检索解决方案,旨在帮助一般开发者针对既有的海量数据,快速而方便地建立自己的全文搜索引擎。全文检索可以帮助您降低服务器搜索负荷、极大程度的提高搜索速度和用户体验。
高性能:后端是采用 C/C++ 开发多线程服务端,索引设计基于 Xapian 和 scws 中文分词。单库最多支持 40 亿条数据,在 5 亿网页大约 1.5TB 的数据中检索时间不超过 1 秒(非缓存)。
简单易用:前端是使用脚本语言编写的开发工具 (SDK),目前仅支持 PHP 语言。API 简单清晰,开发难度极低,提供全中文的示例代码、文档、辅助脚本工具等。
全功能:除支持基础的自定义分词、字段检索、布尔搜索外,还直接支持用户急需的相关搜索、拼音搜索、搜索建议等专业功能。

一、安装Xunsearch服务端

[root@iZ2vcdckpocdmc9n3vlbywZ ~]# yum install -y bzip2
[root@iZ2vcdckpocdmc9n3vlbywZ ~]# wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2
[root@iZ2vcdckpocdmc9n3vlbywZ ~]# tar -xjf xunsearch-full-latest.tar.bz2
[root@iZ2vcdckpocdmc9n3vlbywZ ~]# cd xunsearch-full-1.4.14/
[root@iZ2vcdckpocdmc9n3vlbywZ ~]# sh setup.sh
[root@iZ2vcdckpocdmc9n3vlbywZ ~]# cd /home/wwwroot/xunsearch/
[root@iZ2vcdckpocdmc9n3vlbywZ xunsearch]# bin/xs-ctl.sh -b inet start


二、通过composer安装php搜索包
composer require hightman/xunsearch

三、编写项目配置文件xunseach.ini
具体规则请参考:http://www.xunsearch.com/doc/php/guide/ini.guide

; 项目名称
project.name = article
; 默认字符集
project.default_charset = utf-8
; 索引服务端配置,默认值为 8383
server.index = 127.0.0.1:8383
; 搜索服务端配置,默认值为 8384
server.search = 127.0.0.1::8384
[id]
; 字段类型
type = id
[title]
type = title
[description]
type = string
index = mixed
[content]
type = body
[sort]
type = numeric
[publish_time]
type = numeric


四、生成索引
生成索引是将你数据库中的数据按照一定规则查询出来,然后添加到xunsearch的索引中去,这需要增加一个定时的计划任务,将新增的数据不断的添加进去,才能通过api搜索出来结果。以下的基于thinkphp写的添加索引的一段代码,理解思路即可。

/**
 * 生成索引
 * @return mixed|string
 */
public function index()
{
    //每两分钟执行一次
    //*/2 * * * * /xxxxx/php /xxx/task/index.php article/index 2
    
    $minute = isset($GLOBALS["argv"][2]) ? (int)$GLOBALS["argv"][2] : 0;
    
    $where = [
            ['status','=',1],
    ];
    if ($minute) {
        $where[] = ['updated','>',time()-$minute*60];//多少分钟之前更新的
    }
    
    ArticleModel::where($where)->chunk(500,function($rows) {
        $datas = [];
        
        foreach ($rows as $row){
            $datas[] = [
                    'id' => $row->id, // 此字段为主键,是进行文档替换的唯一标识
                    'title' => $row->title,
                    'description' => $row->description,
                    'content' => strip_tags($row->content),
                    'sort' => $row->sort,
                    'publish_time' => $row->publish_time
            ];
            
        }
        $this->addIndex($datas);
        
    },'id','asc');
    
    die('success');
    
}
private function addIndex($datas){
    try
    {
        //实例化xunsearch对象
        $xs = new \XS('article');
        //使用索引缓冲区
        $xs->index->openBuffer();
        
        foreach ($datas as $data){
            // 创建文档对象
            $doc = new \XSDocument;
            $doc->setFields($data);
            // 更新到索引数据库中
            $xs->index->update($doc);
        }
        
        //告诉服务器重建索引完成
        $xs->index->closeBuffer();
    }
    catch (\XSException $e)
    {
        //echo $e;               // 直接输出异常描述
        if (defined('DEBUG'))  // 如果是 DEBUG 模式,则输出堆栈情况
            echo "\n" . $e->getTraceAsString() . "\n";
    }
    
}


五、搜索功能实现
搜索文档请参考:http://www.xunsearch.com/doc/php/guide/search.overview

public function search(){
    $datas = [];
    
    $keywords = $this->request->param('keywords');
    $page = $this->request->param('page',1);
    $limit = 10;//每页多少条
    $count = 0;//搜出来多少条
    $pageLink = '';//分页代码
    if ($keywords) {
        $xs = new \XS('article');
        $search = $xs->search; // 获取 搜索对象
        $tokenizer = new \XSTokenizerScws;   // 创建分词实例
        $words = $tokenizer->getTokens($keywords);//分词
        $search->setQuery(join(' OR ', $words))->setFuzzy(true);//设置查询条件
        
        //解决统计总条数不准确的问题:始终都用最后一页的总条数
        $search->search();
        $count1 = $search->getLastCount();
        $page1 = ceil($count1/$limit);
        $search->setLimit($limit,($page1-1)*$limit)->search(); 
        $count = $search->getLastCount();
        
        $docs = $search->setLimit($limit, $offset=(($page-1)*$limit))->setSort('publish_time')->search();
        foreach ($docs as &$doc)
        {
            $datas[] = [
                    'id'=>$doc->id,
                    'title'=>$doc->title,
                    'description'=>$doc->description, 
                    'title_h'=>$search->highlight($doc->title,false), // 高亮处理 title 字段
                    'description_h'=>$search->highlight($doc->description,false), // 高亮处理 description 字段
                    //'content'=>$doc->content,
                    'sort'=>$doc->sort,
                    'publish_time'=>$doc->publish_time,
            ];
        }
        
        if ($count>0){
            $pageLink = Bootstrap::make(null, $limit, $page, $count, false, ['path'=>'', 'query'=>['keywords'=>$keywords]])->render();
        }
    }
    
    $this->assign('keywords',$keywords);
    $this->assign('count',$count);
    $this->assign('pageLink',$pageLink);
    $this->assign('datas',$datas);
    
    return $this->fetch('Article/Article-search');
}


关键字xunsearch