千家信息网

sphinx怎么实现多表查询

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这篇文章主要讲解了"sphinx怎么实现多表查询",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"sphinx怎么实现多表查询"吧!sql_query =
千家信息网最后更新 2024年09月22日sphinx怎么实现多表查询

这篇文章主要讲解了"sphinx怎么实现多表查询",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"sphinx怎么实现多表查询"吧!

sql_query = SELECT `id`, 2 AS table_id, `username`, `password`, `email`, `salt`, `from` FROM table_2

  1. ["matches"]=>

  2. array(16) {

  3. [0]=>

  4. array(3) {

  5. ["id"]=>

  6. string(2) "68"

  7. ["weight"]=>

  8. string(1) "2"

  9. ["attrs"]=>

  10. array(1) {

  11. ["table_id"]=>

  12. string(1) "2"

好吧,我又无聊了 Orz

之前搭建的裤子库是单表的,建索引的时候也没考虑什么后续扩展,有小伙伴表示要玩多表查询,于是研究了下……

为嘛不用增量索引呢?本来一个表就10G多够大了,而且增量索引还得不时添加&合并索引……只是本机搭着玩玩,还是算了吧。

翻到一篇文章,里面说到了配置文件里的继承和重载,对于添加多个数据源还是挺有帮助的,摘抄下:

定义父类email

source email {     ....}

定义子类subemail继承email类的所有设置:

source subemail : email { #除了source,index也可以使用继承    ....}

子类中可以重载email中的设置

source subemail : email {    sql_host      = www.ibos.com.cn    #重载主机    sql_query    = SELECT * FROM subemail    #重载sql_query语句}

其实继承很少被使用到,但有一个很实用的例子就是有很多数据源使用同一数据库的时候,继承就派上用场了

source setdb {     #setdb类只实现连接数据库    sql_host                  =     localhost    sql_user                  =     root    sql_pass                  =     root    sql_db                     =     ibos    sql_port                   =     3306}souce email : setdb{    #继承setdb类    sql_query = ...        #直接写查询语句,而不用再写数据库信息}souce diary : setdb {    sql_query = ...  } souce article : setdb {    sql_query = ...  }souce forum : setdb {    sql_query = ...  }

然后我在上一次的配置文件基础上改了改,加上了另一个表做数据源。
但是在改 php 文件时发现个问题:之前的源码里用的是 $sql = "select * from table_1 where id in($ids)" ,现在加了另一个表以后就不好搞了。

因为两个表的 ID 字段都是从 1 开始自增的,如果用多表 Union 的话可能把两个表中的同一个 ID 的行取出来。有个解决办法就是把第二个表 ID 的自增起始数值改成第一个表 ID 的结束数值-- 不过这个方法只适用极少的情况……

接着百度了很久无果,谷歌也搜不到…… 后来把搜索关键词换为 coreseek indexes in different tables 就搜到一大堆了 Orz

根据这个 Using Sphinx with PHP with multiple indexes 的回答,把配置文件重新改了下:

#源定义source table_1{    type                    = mysql    sql_host                = localhost    sql_user                = test    sql_pass                = test    sql_db                    = sed    sql_port                = 3306    sql_query_pre            = SET NAMES utf8    sql_query                = SELECT `id`, 1 AS table_id, `username`, `password`, `email`, `salt`, `from` FROM table_1    sql_attr_uint            = table_id         #从SQL读取到的值必须为整数    #sql_attr_timestamp        = date_added  #从SQL读取到的值必须为整数,作为时间属性    sql_query_info_pre      = SET NAMES utf8                                        #命令行查询时,设置正确的字符集    sql_query_info            = SELECT * WHERE ID=$id #命令行查询时,从数据库读取原始数据信息}source table_2 : table_1{    sql_query = SELECT `id`, 2 AS table_id, `username`, `password`, `email`, `salt`, `from` FROM table_2}#index定义index table_1{    source            = table_1    #对应的source名称    path            = E:/SQL_DATA/coreseek/var/data/table_1 #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...    docinfo            = extern    mlock            = 0    morphology        = none    min_word_len        = 1    ondisk_dict     = 1    html_strip                = 0    #中文分词配置,详情请查看:http://www.coreseek.cn/products-install/coreseek_mmseg/    #charset_dictpath = /usr/local/mmseg3/etc/ #BSD、Linux环境下设置,/符号结尾    charset_dictpath = E:/SQL_DATA/coreseek/etc/ #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...    charset_type        = zh_cn.utf-8}index table_2 : table_1{    source = table_2    path =  E:/SQL_DATA/coreseek/var/data/table_2}#全局index定义indexer{    mem_limit            = 1024M}#searchd服务定义searchd{    listen                  =   9000    read_timeout        = 5    max_children        = 30    max_matches            = 1000    seamless_rotate        = 0    preopen_indexes        = 0    unlink_old            = 1    pid_file = E:/SQL_DATA/coreseek/var/log/searchd_mysql.pid  #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...    log = E:/SQL_DATA/coreseek/var/log/searchd_mysql.log        #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...    query_log = E:/SQL_DATA/coreseek/var/log/query_mysql.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...    binlog_path =                                #关闭binlog日志}

所以给返回的 matches 加个 table_id 的属性就好了,建好索引后查询时 matches 返回值类似这样:

["matches"]=>  array(16) {    [0]=>    array(3) {      ["id"]=>      string(2) "68"      ["weight"]=>      string(1) "2"      ["attrs"]=>      array(1) {        ["table_id"]=>        string(1) "2"      }    }    [1]=>    array(3) {      ["id"]=>      string(3) "350"      ["weight"]=>      string(1) "2"      ["attrs"]=>      array(1) {        ["table_id"]=>        string(1) "1"      }    }

需要注意的是如果之前有把 searchd 注册成服务的话要记得换个端口……

最后改一下用于搜索的 PHP 文件(渣代码勿怪…):

SetServer('127.0.0.1', 9000);    $cl->SetConnectTimeout(3);    $cl->SetArrayResult(true);    // 设置是否全文匹配    if (!empty($_GET) && !empty($_GET['f'])) {        $cl->SetMatchMode(SPH_MATCH_ALL);    } else {        $cl->SetMatchMode(SPH_MATCH_ANY);    }    if (!empty($_GET) && !empty($_GET['p'])) {        $p = !intval(trim($_GET['p'])) == 0 ? intval(trim($_GET['p'])) - 1 : 0;        $p = $p * 20;        // 我在sed.conf 设置了最大返回结果数1000。但是我在生成页码的时候最多生成20页,我想能满足大部分搜索需求了。        // 以下语句表示从P参数偏移开始每次返回20条。        $cl->setLimits($p, 20);    } else {        $cl->setLimits(0, 20);    }    $res = $cl->Query("$Keywords", "*");    //var_dump($res);    @mysql_connect("localhost", "test", "test"); //数据库账号密码    mysql_select_db("sed"); //数据库库名名    mysql_query("set names utf8");    $tables = ['table_1', 'table_2'];  //把表名放入数组    function getResult($id, $table)    {            $sql    = "select * from {$table} where id = " . $id;            $result = mysql_query($sql);            while ($row = mysql_fetch_array($result)) {                echo "" . $row['username'] . "";                echo "" . $row['email'] . "";                echo "" . $row['password'] . "";                echo "" . $row['salt'] . "";                echo "" . $row['from'] . "";            }    }    if ($res["total_found"]) {        $num = $res["total_found"];    } else {        $num = 0;    }}?>   The Web of Answers                         

找到与 {$Keywords} 相关的结果 {$num} 个。用时 {$res['time']} 秒。
"; echo "
"; if (is_array($res["matches"])) { foreach ($res["matches"] as $docinfo) { $table_id = $docinfo['attrs']['table_id']; getResult($docinfo['id'], $tables[$table_id - 1]); } } echo "
Username Email Password Salt From
"; } else { if (!empty($_GET) && !empty($_GET['q'])) { echo "
找不到与 {$Keywords} 相关的结果。请更换其他关键词试试。
"; }}?>

感谢各位的阅读,以上就是"sphinx怎么实现多表查询"的内容了,经过本文的学习后,相信大家对sphinx怎么实现多表查询这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0