sphinx实时搜索代码

42 篇文章 0 订阅
37 篇文章 0 订阅

sphinx实时索引效率很高,上千万条记录也能在不到一秒时间内搜索出来,这一点有时候可以作为数据库的预处理,比如,搜索出的新闻Id,再根据这些Id分页显示,效率很高,基本上如果是搜索导致并发性很高的网站,或搜索导致数据库性能成为瓶颈的网站,都可以这样处理一下,减少数据库的查询,我们都知道,数据库的like全查询,那是不走索引的,基本上几百万条数据可能效率就很低了。

这里是一个实例,需要的话请参考,谢谢您的关注。

首先添加一个配置文件 rt_article.conf

index rt_article
{
        type                = rt
        rt_mem_limit        = 512M
        path                = /data/sphinx/data/rt_article
        docinfo             = extern
        #charset_type        = utf-8

        morphology          = none
        min_word_len        = 1
        min_prefix_len      = 0
        html_strip          = 1
        html_remove_elements = style, script


        rt_field            = articleName
        rt_field            = tags
        rt_field            = content

        rt_attr_timestamp   = announceTime

        rt_attr_string      = title
        rt_attr_string      = keywords
        rt_attr_string      = newsContent

    ngram_len               = 1
    
    #ngram_chars            = 0..9, _, a..z, U+3000..U+2FA1F
    #charset_table          = 0..9, A..Z->a..z, _, a..z, U+3000..U+2FA1F
    
    #ngram_chars            = 0..9, _, a..z, U+00A0..U+2FFFF
    #charset_table          = 0..9, A..Z->a..z, _, a..z, U+00A0..U+2FFFF
    
    ngram_chars             = U+4E00..U+9FBF, U+3400..U+4DBF, U+20000..U+2A6DF, U+F900..U+FAFF,\
                                  U+2F800..U+2FA1F, U+2E80..U+2EFF, U+2F00..U+2FDF, U+3100..U+312F, U+31A0..U+31BF,\
                                  U+3040..U+309F, U+30A0..U+30FF, U+31F0..U+31FF, U+AC00..U+D7AF, U+1100..U+11FF,\
                                  U+3130..U+318F, U+A000..U+A48F, U+A490..U+A4CF, 0..9, _, a..z
}

searchd
{    
        listen                  = 9312
        listen                  = 9306:mysql41
        
        log                     = /usr/local/sphinx/var/log/searchd.log
        query_log               = /usr/local/sphinx/var/log/query.log
     
        read_timeout            = 5
        client_timeout          = 300
     
        max_children            = 30
        persistent_connections_limit    = 30

        pid_file                = /usr/local/sphinx/var/log/searchd.pid

        seamless_rotate         = 1
        preopen_indexes         = 1
        unlink_old              = 1
        mva_updates_pool        = 1M
        max_packet_size         = 8M
        max_filters             = 256

        max_filter_values       = 4096
        max_batch_queries       = 32
        workers                 = threads # for RT to work

        binlog_path             = /usr/local/sphinx/var/data 
}

然后 ./bin/searchd --config=/usr/local/sphinx/etc/rt_article.conf

启动了sphinx服务后,可以先写一段代码向索引中插入一些记录(这些记录实际中是从mysql读取后写入的)先写

先插入一些数据,然后再测试查询 sphinx_article.php,内容如下:

<?php

    $link = mysql_connect('127.0.0.1:9306') or die('can not connect server');
    if (! $link) {
        echo mysql_errno().': ' . mysql_error()."\n";
    }
    
    $id = 27;
    $articleName = '学习linux吧,最好是lnmp方面的知识';
    $tags = 'linux,nginx,mysql,php,python';
    $content = '本文介绍的Linux定制专栏文章关于Gnome 3桌面,这种桌面与Xfce和KDE大不一样。作者在本文中介绍了配置和定制Gnome外壳的方法,但由于Gnome 3采用了模块化设计方式,还可以把Gnome外壳完全换成别的系统,这种系统提供了全然不同的桌面,配置和定制方面有着全然不同的可能性。';
    $announceTime = time();
    
    $sql = "insert into rt_article(id,articleName,tags,content,title,keywords,newsContent,announceTime) values($id,'{$articleName}','{$tags}','{$content}','{$articleName}','{$tags}','{$content}',{$announceTime}) ";
    $result = mysql_query($sql);
    if(! $result) {
        echo '未能执行成功!'."\n";
    }
    if(mysql_errno()) {
        echo mysql_errno().': '.mysql_error()."\n";
        echo $sql;
        mysql_close($link);
        exit;
    }
    
    $query = mysql_query("select * from rt_article where match('配置');");
    if(mysql_errno()) {
        echo mysql_errno().': '.mysql_error()."\n";
        mysql_close($link);
        exit;
    }
    while($row = mysql_fetch_row($query,MYSQL_ASSOC))
    {
        var_dump($row);
    }    
    mysql_close($link);
    exit;
    
?>

运行,如何能正确查询出插入的那条数据,就没有问题了

然后测试一下搜索:

文件sphinx_test.php,注意这里引用了sphinxapi.php,我改名了,为sphinx_client.php

这里假定搜索框中的关键词是用空格分开的,然后测试一下搜索吧。

<?php

include('sphinx_client.php');

$sphinx_client = new SphinxClient();
$sphinx_client->SetServer('192.168.1.192',9312);

//$sphinx_client->SetArrayResult(TRUE);

//$sphinx_client->SetIDRange(1,20);

//$sphinx_client->SetFilter('group_id',[1,2]);

$sphinx_client->SetLimits(0,100);

$weights = ['articleName'=>3,'tags'=>2,'content'=>1];

$sphinx_client->SetFieldWeights($weights);

if(! empty($_POST['keywords'])) {
    $keywords = htmlentities($_POST['keywords']);
    $keywords = explode(' ',$keywords);


    // 排序:有关键字查询则用相关度排序,否则用 id 倒排
    $sphinx_client->SetSortMode(SPH_SORT_RELEVANCE);

    //排序,weight第一,id降序排列
    $sphinx_client->SetSortMode(SPH_SORT_EXTENDED, '@weight desc,$id desc');

    $tmpArr = [];
    $str_query = '';
    foreach($keywords as $value) {

        $str_query .= '"'.$value.'" | ';
        $res = $sphinx_client->Query('@tags ('.$value.')', 'rt_article');
        if(isset($res['matches'])) {
            $searchedArr = array_keys($res['matches']);
            echo $value.json_encode($searchedArr).'<br/>';

            if(count($tmpArr) >0) {
                $tmpArr = array_intersect($tmpArr,$searchedArr);
            }
            else {
                $tmpArr = $searchedArr;
            }
        }
    }
    $result = array_values($tmpArr);
    echo '111,result:'.json_encode($result).'<br/>';

    if(count($result) < 3) {
        $str_query = substr($str_query,0,-2);
    }
    $res = $sphinx_client->Query('@tags ('.$str_query.')', 'rt_article');
    if(isset($res['matches'])) {
        $ret = array_keys($res['matches']);

        echo '222,ret:'.json_encode($ret).'<br/>';

        $result = array_unique(array_merge($result,$ret));
    }

    echo '333,result:'.json_encode(array_values($result)).'<br/>';

    


    // $sphinx_client->SetMatchMode(SPH_MATCH_EXTENDED2);
    // $res = $sphinx_client->Query('@title (测试)','rt');

    // $res = $sphinx_client->Query('@title (测试) @content (网络)','rt');

    echo '<pre>';
    //var_dump($res);
    print_r($sphinx_client->GetLastError());
    print_r($sphinx_client->GetLastWarning());
    echo '</pre>';
}
else {
    $sphinx_client->SetSortMode(SPH_SORT_EXTENDED, '@id DESC');
    $res = $sphinx_client->Query('','rt_article');

    echo '<pre>';

    print_r($res['matches']);
    //var_dump($res);
    print_r($sphinx_client->GetLastError());
    print_r($sphinx_client->GetLastWarning());
    echo '</pre>';
}


function searchArticle($keywords)
{    
    $str_query = '';
    foreach($keywords as $value) {
        $str_query .= '"'.$value.'" | ' ;
    }
    $str_query = substr($str_query,0,-2);
    $str_query = "'{$str_query}'";
    echo "[$str_query]";

    // 排序:有关键字查询则用相关度排序,否则用 id 倒排
    $sphinx_client->SetSortMode(SPH_SORT_RELEVANCE);

    //排序,weight第一,id降序排列
    $sphinx_client->SetSortMode(SPH_SORT_EXTENDED, '@weight desc,$id desc');

    $res = $sphinx_client->Query($str_query,'rt_article');


    // $sphinx_client->SetMatchMode(SPH_MATCH_EXTENDED2);
    // $res = $sphinx_client->Query('@title (测试)','rt');

    // $res = $sphinx_client->Query('@title (测试) @content (网络)','rt');

    echo '<pre>';
    if(isset($res['matches'])) {    
        print_r($res['matches']);
    }
    //var_dump($res);
    print_r($sphinx_client->GetLastError());
    print_r($sphinx_client->GetLastWarning());
    echo '</pre>';
}

function getRecommend($keywords)
{
    $tmpArr = [];
    $str_query = '';
    foreach($keywords as $value) {

        $str_query .= '"'.$value.'" | ';
        $res = $sphinx_client->Query('@tags ('.$value.')', 'rt_article');
        if(isset($res['matches'])) {
            $searchedArr = array_keys($res['matches']);
            echo $value.json_encode($searchedArr).'<br/>';

            if(count($tmpArr) >0) {
                $tmpArr = array_intersect($tmpArr,$searchedArr);
            }
            else {
                $tmpArr = $searchedArr;
            }
        }
    }
    $result = array_values($tmpArr);
    echo '111,result:'.json_encode($result).'<br/>';

    if(count($result) < 3) {
        $str_query = substr($str_query,0,-2);
    }
    $res = $sphinx_client->Query('@tags ('.$str_query.')', 'rt_article');
    if(isset($res['matches'])) {
        $ret = array_keys($res['matches']);

        echo '222,ret:'.json_encode($ret).'<br/>';

        $result = array_unique(array_merge($result,$ret));
    }

    echo '333,result:'.json_encode(array_values($result)).'<br/>';
}

?>


<!DOCTYPE html>
<html>
<head>
<title>健康资讯详情分享版</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection" content="telephone=no">
</head>
<body>
    <div style="width:100%">
        <form action="sphinx_test.php" method="post">
        <input type="text" name="keywords" value="" placeHolder="请输入关键字,中间以空格分开" />
        <input type="submit" name="btnSubmit" value="搜索">
        </form>
    </div>
</body>
</html>



//可以使用mysql客户端来查找或更新sphinx的内容 根据产品英文名来匹配查找sphinx
        select * from rt_goods where match('@productpinyin gmrjn');//查找感冒软胶囊 英文拼音 rt_field为productpinyin的字段内容包含gmrjn的记录都会被查询出来
        select * from rt_goods where match('@productpinyin ^gmrjn$');//rt_field为productpinyin的字段内容精确匹配gmrjn的记录都会被查询出来,这样差比较准。


Coreseek 全文检索服务器 2.0 (Sphinx 0.9.8)参考手册和源程序 手册內容: 文档版本:v0.9 目录 1. 简介 1.1. 什么是 Sphinx 1.2. Sphinx 的特性 1.3. 如何获得 Sphinx 1.4. 许可协议 1.5. 作者和贡献者 1.6. 开发历史 2. 安装 2.1. 支持的操作系统 2.2. 依赖的工具 2.3. 安装 Sphinx 2.4. 已知的问题和解决方法 2.5. Sphinx 快速入门教程 3. 建立索引 3.1. 数据源 3.2. 属性 3.3. 多值属性 ( MVA : multi-valued attributes) 3.4. 索引 3.5. 数据源的限制 3.6. 字符集 , 大小写转换 , 和转换表 3.7. SQL 数据源 (MySQL, PostgreSQL) 3.8. xmlpipe 数据源 3.9. xmlpipe2 数据源 3.10. 实时索引 更新 3.11. 索引合并 4. 搜索 4.1. 匹配模式 4.2. 布尔查询 4.3. 扩展查询 4.4. 权值计算 4.5. 排序模式 4.6. 结果分组(聚类) 4.7. 分布式搜索 4.8. searchd 日志格式 5. API 参考 5.1. 通用 API 方法 5.1.1. GetLastError 5.1.2. GetLastWarning 5.1.3. SetServer 5.1.4. SetRetries 5.1.5. SetArrayResult 5.2. 通用搜索设置 5.2.1. SetLimits 5.2.2. SetMaxQueryTime 5.3. 全文搜索设置 5.3.1. SetMatchMode 5.3.2. SetRankingMode 5.3.3. SetSortMode 5.3.4. SetWeights 5.3.5. SetFieldWeights 5.3.6. SetIndexWeights 5.4. 结果集过滤设置 5.4.1. SetIDRange 5.4.2. SetFilter 5.4.3. SetFilterRange 5.4.4. SetFilterFloatRange 5.4.5. SetGeoAnchor 5.5. GROUP BY 设置 5.5.1. SetGroupBy 5.5.2. SetGroupDistinct 5.6. 搜索 5.6.1. Query 5.6.2. AddQuery 5.6.3. RunQueries 5.6.4. ResetFilters 5.6.5. ResetGroupBy 5.7. 额外的方法 5.7.1. BuildExcerpts 5.7.2. UpdateAttributes 6. MySQL 存储引擎 (SphinxSE) 6.1. SphinxSE 概览 6.2. 安装 SphinxSE 6.2.1. 在 MySQL 5.0.x 上 编译 SphinxSE 6.2.2. 在 MySQL 5.1.x 上编译 SphinxSE 6.2.3. SphinxSE 安装测试 6.3. 使用 SphinxSE 7. 报告 bugs 8. sphinx.conf 选项参考 8.1. Data source 配置选项 8.1.1. type 8.1.2. sql_host 8.1.3. sql_port 8.1.4. sql_user 8.1.5. sql_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值