您好,登錄后才能下訂單哦!
這篇文章主要講解了“sphinx怎么實現多表查詢”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“sphinx怎么實現多表查詢”吧!
sql_query = SELECT `id`, 2 AS table_id, `username`, `password`, `email`, `salt`, `from` FROM table_2
["matches"]=>
array(16) {
[0]=>
array(3) {
["id"]=>
string(2) "68"
["weight"]=>
string(1) "2"
["attrs"]=>
array(1) {
["table_id"]=>
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 文件(渣代碼勿怪…):
<?php // 引用sphinxapi類 require "sphinxapi.php"; //關閉錯誤提示 error_reporting(E_ALL & ~E_NOTICE); $num = 0; if (!empty($_GET) && !empty($_GET['q'])) { $Keywords = strip_tags(trim($_GET['q'])); if (!empty($_GET['m']) && 1 == $_GET['m']) { $Keywords = substr(md5($Keywords), 8, 16); } if (!empty($_GET['m']) && 2 == $_GET['m']) { $Keywords = md5($Keywords); } $cl = new SphinxClient(); // 返回結果設置 $cl->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 "<tr><td>" . $row['username'] . "</td>"; echo "<td>" . $row['email'] . "</td>"; echo "<td>" . $row['password'] . "</td>"; echo "<td>" . $row['salt'] . "</td>"; echo "<td>" . $row['from'] . "</td></tr>"; } } if ($res["total_found"]) { $num = $res["total_found"]; } else { $num = 0; } } ?> <!DOCTYPE html> <html> <head> <title>The Web of Answers</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-with,initial-scal=1"> <link href="css/bootstrap.min.css" rel="stylesheet"> <script src="js/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script> function check(form){ if(form.q.value==""){ alert("Not null !"); form.q.focus(); return false; } } </script> <style> h2 { font-family: Times New Roman, Lucida Handwriting; } body { background-image: url(img/bg.jpg); } </style> </head> <body> <div class="container" id="container"> <div id="page-header"> <h2 class="text-center"> The Web of Answers </h2> </div> <div class="row"> <form action="" method="get" class="form-horizontal" role="form"> <div id="checkbox" class="col-md-6 col-md-offset-3"> <label class="checkbox-inline"> <input type="checkbox" id="full" name="f" value="1"> 完整匹配 </label> <label class="checkbox-inline"> <input type="checkbox" id="md5_16" name="m" value="1"> MD5匹配(16位) </label> <label class="checkbox-inline"> <input type="checkbox" id="md5_32" name="m" value="2"> MD5匹配(32位) </label> </div> <div class="input-group col-md-6 col-md-offset-3"> <input type="text" class="form-control" name="q" placeholder="請輸入" value="<?php echo strip_tags(trim($_GET['q']));?>"> <div class="input-group-btn"> <button type="submit" class="btn btn-primary" onclick="check(form)">Search</button> </div> </div> </form> </div> <br> <?php if (0 != $num) { echo "<div class=\"row\"> <div class=\"alert alert-success alert-dismissible col-md-10 col-md-offset-1\" role=\"alert\"> <button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span aria-hidden=\"true\">×</span><span class=\"sr-only\">Close</span></button> 找到與<b> {$Keywords} </b>相關的結果 {$num} 個。用時 {$res['time']} 秒。</div>"; echo "<div class=\"table-responsive col-md-10 col-md-offset-1\"> <table class=\"table table-striped table-hover\"> <tr> <th>Username</th> <th>Email</th> <th>Password</th> <th>Salt</th> <th>From</th> </tr>"; if (is_array($res["matches"])) { foreach ($res["matches"] as $docinfo) { $table_id = $docinfo['attrs']['table_id']; getResult($docinfo['id'], $tables[$table_id - 1]); } } echo "</table></div></div>"; } else { if (!empty($_GET) && !empty($_GET['q'])) { echo "<div class=\"alert alert-warning alert-dismissible col-md-10 col-md-offset-1\" role=\"alert\"> <button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span aria-hidden=\"true\">×</span><span class=\"sr-only\">Close</span></button> 找不到與<b> {$Keywords} </b>相關的結果。請更換其他關鍵詞試試。</div></div>"; } } ?> <div id="pages"> <center> <nav> <ul class="pagination"> <?php if ($num !== 0) { $pagecount = (int) ($num / 20); if (!($num % 20) == 0) { $pagecount = $pagecount + 1; } if ($pagecount > 20) { $pagecount = 20; } $highlightid = !intval(trim($_GET['p'])) == 0 ? intval(trim($_GET['p'])) : 1; for ($i = 1; $i <= $pagecount; $i++) { if ($highlightid == $i) { echo "<li class=\"active\"><a href=\"#\">{$i}<span class=\"sr-only\">(current)</span></a></li>"; } else { echo "<li><a href=\"index.php?q={$Keywords}&p={$i}\">{$i}</a></li>"; } } } ?> </ul> </nav> </center> </div> <div id="footer"> <p class="text-center"> The Web of Answers ©2010-2015 | Powered by b0rg </p> </div> </div> </body> </html>
感謝各位的閱讀,以上就是“sphinx怎么實現多表查詢”的內容了,經過本文的學習后,相信大家對sphinx怎么實現多表查詢這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。