好吧,我又无聊了 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>
h1 {
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">
<h1 class="text-center"> The Web of Answers </h1>
</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中文分词搜索coreseek windows下安装与基本使用简介
Using Sphinx with PHP with multiple indexes
[...]代码写的非常不拘小节,大家就不要指责了,能用就行。reference:shiniv,,1/08/2013hanxiao2100,,14/01/2014melonol,,4/05/2013岚光,,11/02/2015barryhunter,,24/11/2012 March 31, 2015March 31, 2015 A11riseforme hackpentest Post navigat[...]
mysql装在不同的服务器上,coreseek 如果采用分布式索引 php页面怎么处理?
把mysql_connect改一改不就好了…
我的意思是有两台或多台 mysql 服务器
coreseek 的多服务器、多库查询相关资料很少,不过sphinx的倒是一大堆,估计都差不多的。
给两个链接供参考:
Sphinx 多服务器 多库 多表 取源数据 (http://www.zhouchen33.com/index.php/archives/775)
Sphinx replication (http://www.ivinco.com/blog/sphinx-replication/)
或者Google下sphinx over multiple servers and database partitions,
或者用Python搞分布式查询,
祝好运 2333
谢了 有空我研究下
你好,按照你的步骤我做了,我在CMD查询coreseek 的时候结果是正确的,但是用你写好的PHP一直提示没有结果,是什么原因呢,我php是个渣渣,求指教
这个PHP代码是凌晨3点写的… 当时已经思维混乱了,而且裤子的配置我已经删了,所以也不知道是哪里有bug Orz
你可以参考这个…… http://y.oulove.me/building_big_data_retrieval_system/
额。打不开这网站,翻墙都打不开
有个配置你写错了,应该是这样的,我测试过的
sql_query_info = SELECT id, 01 AS sgk_id, username, password, email FROM table_1 WHERE id=$id
那个网站你可以看google快照…
因为有不少人表示有问题我就又重新配了一遍,顺便把PHP代码也优化了下……
至于你所说的sql_query_info实际上可以那样写的,只是在console查的时候会报错,网页里查的时候没影响。
如果还是不行的话检查下用户名或者密码或者数据库名什么的是不是忘了改……
囧,y.oulove.me这个网站俺给关掉了,不过有英文版的可以参考一下,http://www.websec.co/archives/Building_Big_Data_Retrieval_System.htm
谢谢,快照我看了,PHP源码我也修改好了,PS:PHP你修改的和我如此的相似哈哈
你好,请问php怎么写模糊查询语录?
你的意思是SQL的模糊查询吧……
使用 like 操作符,
具体的自己看看吧:
http://www.w3school.com.cn/sql/sql_like.asp
能不能3张表,4张表,,更多。。。?
我照猫画虎搞,好像出问题了,2张表可以,多张表,只能查到一张表的内容了
displaying matches:
document=32, weight=1727, table_id=4FATAL: sql_query_info: mysql_query: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE ID=32' at line 1
./search xxx 命令行多表查询时会报错, 如果第一张表中已查询到结果,就不会再查询其它表了
本来在命令行里就只能查一个表,
PHP文件的作用就是实现多表查询,好好看看代码吧~
source newdb2 : newdb1
sql_query = SELECT `id`, 2 AS table_id, `username`, `password`, `email`, `salt`, `site` FROM newdb2{
}
source newdb3 : newdb1
sql_query = SELECT `id`, 3 AS table_id, `username`, `password`, `email`, `salt`, `site` FROM newdb3{
}
index newdb2 : newdb1
source = newdb2 path = /usr/local/coreseek/var/data/newdb2{
}
index newdb3 : newdb1
source = newdb3 path = /usr/local/coreseek/var/data/newdb3{
}
这是修改的配置,麻烦大神给看看
感觉没问题,估计是没改PHP文件……
看看PHP文件里的41行,新添加的表名要放入数组里。
或者可以改改用 SELECT TABLES FROM XXX 查出所有表名免得每次都要手工改。
谢谢,我试试,不过数组里我已经添加过了,好像没效果啊
$tables = ['newdb1', 'newdb2', 'newdb3']; //把表名放入数组
测试发现:
table1,table2,table3,都有 abc@qq.com,应该会查到3条结果,但实际只有1条;
table1,table2,table3,3张表仅有一个abc@qq.com,可以正常查到,显示1条结果;
明白了,如果两个表中的两条记录ID相同,则只返回一条结果
说一下感受,现在凑合能用了,一个表2亿多条,20G的样子,生成索引时各种报错,各种参数更改、百度谷歌无果,后来更换SSD盘,每个表5000万条,能够较顺利生成索引了,但最后一步又是报错,(Killed35.5 of 551.5 MB, 60.8% done),各种办法都试了还是不行。最后放了2亿数据上去,不带符号的值查询很快,如woaini、9998877等,只要0.00秒,如果是一个完整的email,匹配太久,时间长达10秒,看看tingmima就知道,慢得已经无法忍受了,普通情况下大量数据sphinx/coreseek也是苍白无力的,时间和精力有限,已经准备放弃折腾了。 当然,你如果有力折腾,其实速度还是可以提升的,研究一下多线程。
折腾这么久也是蛮拼的… 好像你是在Linux下搞这个吧?
这个是我在windows下测试通过的,用了两个表,每个表1亿多条数据,生成索引按着步骤来的话没遇到过你的问题。
最后多进程和分布式才是王道,本机上折腾玩玩就够了 2333
还有貌似在coreseek里是不能搜@这个符号的,因为它在sql里有特殊含义…
然后看了一下那个getResult函数效率还是很低,因为是从表里一条条的取数据…我也懒得改了 Orz
可以试试先从matches里取出每个表对应的一堆id组成ids,然后像上篇文章里的那样 select * from xxx where id in(ids)
估计会快很多…
我按照你的脚本来写,也都看了所有回复,但是...还是遇到了问题,
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in D:phpStudyWWWindex.php on line 41
41:while ($row = mysql_fetch_array($result))
然后看了下,attrs没有数据传出来.这个是为什么呢....
如果console里没问题的话,那估计是忘了改php文件…
sql_query = SELECT id, 1 AS table_id, username, password, email, salt, from FROM table_1
这句话这样
sql_query = SELECT id, 1 AS table_id, username, email from FROM table_1
PHP文件改了数据库连接表名然而还是显示空白怎么破
Parse error: syntax error, unexpected '[' in D:wwwrootLocalUsera222wwwindex.php on line 40
$tables=['soyun','dnf']; //把表名放入数组
哪里错了???
$tables=array('soyun','dnf'); //把表名放入数组
改成这样就行了然而搜索时只输出找到多少条,不输出数据怎么回事
你php版本过低不支持用[]表示数组,至于源码你去http://www.findmima.com/下载吧,他把坑都填了 23333
PHP代码44行
$sql = "select * from {$table} where id = " . $id;
查不出来,发现是SQL语句错了,求解怎么改
配置文件:
type = mysql sql_host = localhost sql_user = ly sql_pass = a123456 sql_db = ly sql_port = 3306 sql_query_pre = SET NAMES utf8 sql_query = SELECT `id`, 1 AS table_id, `qq`, `password`, `ip` FROM t_qq_5 sql_attr_uint = table_id #sql_attr_timestamp = date_added sql_query_info_pre = SET NAMES utf8 sql_query_info = SELECT * WHERE ID=$idsource sgk_1
{
}
source t_qq_6 : sgk_1
sql_query = SELECT `id`, 2 AS table_id, `qq`, `password`, `ip` FROM t_qq_6{
}
sql_query = SELECT `id`, 3 AS table_id, `qq`, `password`, `ip` FROM t_qq_10source t_qq_10 : sgk_1
{
}
index sgk_1
source = sgk_1 path = /usr/local/coreseek/var/data/sgk_1 docinfo = extern mlock = 0 morphology = none min_word_len = 1 ondisk_dict = 1 html_strip = 0 charset_dictpath = /usr/local/mmseg3/etc/ charset_type = zh_cn.utf-8{
}
index t_qq_6 : sgk_1
source = t_qq_6 path = /usr/local/coreseek/var/data/t_qq_6{
}
source = t_qq_10 path = /usr/local/coreseek/var/data/t_qq_10index t_qq_10 : sgk_1
{
}
indexer
mem_limit = 1024M{
}
searchd
listen = 9000 read_timeout = 5 max_children = 30 max_matches = 1000 seamless_rotate = 0 preopen_indexes = 0 unlink_old = 1 pid_file = /usr/local/coreseek/var/log/searchd_mysql.pid log = /usr/local/coreseek/var/log/searchd_mysql.log query_log = /usr/local/coreseek/var/log/query_mysql.log{
}
PHP程序用的你的.搜索不出数据,打印$res为什么是false?
QAQ 不打印数据 $res没有传回table_id
博主您好,按您说的方面 加了三个数据表,,现在table1,table2都可以正常搜索,第三个表,显示不出来,但是索引是成功的!
×Close 找到与 小老虎 相关的结果 8 个。用时 0.004 秒。
Username Email Password Salt From
1(current)
如果是2000张表怎么办 这样写配置文件不点累死啊
[...]岚光,Coreseek多表索引搜索[...]
启用服务的时候 提示 out of memory 到现在还没解决办法
同out of memory goole百度半天都没解决= =
站长有没有好点的源码????分享下