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

创新互联长期为成百上千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为磁县企业提供专业的成都网站制作、成都做网站,磁县网站改版等技术服务。拥有10余年丰富建站经验和众多成功案例,为您定制开发。
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 文件(渣代码勿怪…):
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
The Web of Answers
找到与 {$Keywords} 相关的结果 {$num} 个。用时 {$res['time']} 秒。";
echo "
Username
Email
Password
Salt
From
";
if (is_array($res["matches"])) {
foreach ($res["matches"] as $docinfo) {
$table_id = $docinfo['attrs']['table_id'];
getResult($docinfo['id'], $tables[$table_id - 1]);
}
}
echo "
";
} else {
if (!empty($_GET) && !empty($_GET['q'])) {
echo "
找不到与 {$Keywords} 相关的结果。请更换其他关键词试试。The Web of Answers ©2010-2015 | Powered by b0rg
感谢各位的阅读,以上就是“sphinx怎么实现多表查询”的内容了,经过本文的学习后,相信大家对sphinx怎么实现多表查询这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!