zoukankan      html  css  js  c++  java
  • 【PHP高效搜索专题(2)】sphinx&coreseek在PHP程序中的应用实例

    PHP可以通过三种途径来调用sphinx

    • 通过Sphinx官方提供的API接口(接口有Python,Java,Php三种版本)
    • 通过安装SphinxSE,然后创建一个中介sphinxSE类型的表,再通过PHP执行,采用sphinxSE必须要求为mySQL安装sphinxSE Engine驱动行特定的SQL语句实现
    • 使用libsphinxclient+php的sphinx扩展 代替 sphinxapi (等同于第一种方案)

    通过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来链接

    直接进解压后的包里面找到sphinxapi.php,然后引入到文件中,其它操作都同上.虽然Coreseek官方教程中建议php使用直接include一个php文件进行操作,事实上php有独立的sphinx模块可以直接操作coreseek(coreseek就是sphinx!)已经进入了php的官方函数库,而且效率的提升不是一点点!但php模块依赖于libsphinxclient包。见上文;

    SphinxSE

    SphinxSE是一个可以编译进MySQL 5.x版本的MySQL存储引擎,它利用了该版本MySQL的插件式体系结构。尽管被称作“存储引擎”,SphinxSE自身其实并不存储任何数据。它其实是一个允许MySQL服务器与searchd交互并获取搜索结果的嵌入式客户端。所有的索引和搜索都发生在MySQL之外。

    SphinxSE的适用于:

    • 使将MySQL FTS 应用程序移植到Sphinx
    • 使没有Sphinx API的那些语言也可以使用Sphinx
    • 当需要在MySQL端对Sphinx结果集做额外处理(例如对原始文档表做JOIN,MySQL端的额外过滤等等)时提供优化。

    要通过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扩展模块来要远远不足。。。

  • 相关阅读:
    【canvas】--------------处理canvas物理像素模糊问题-------------【劉】
    【js】--------------判断一个对象是否有某个属性-------------【劉】
    【vue】--------------vue+element-ui实现分页效果-------------【劉】
    【html】--------------iframe-------------【劉】
    【劉】---------------单页面和多页面的区别
    【react】--------------flux-------------【劉】
    【vue】--------------vue路由懒加载-------------【劉】
    【git】--------------git基本指令-------------【劉】
    【git】--------------git基本介绍-------------【劉】
    datatable 分组
  • 原文地址:https://www.cnblogs.com/nixi8/p/4746189.html
Copyright © 2011-2022 走看看