2012-07-16 119 views
7

我目前正在编写自己的CMS,并且我在search.php处。我只需在一个查询中搜索4个具有不同列名的表,因为我的服务器不是最快的。MySQL - 搜索PHP脚本

有我的DB安排:

cmw_admin(用户表)

+-----------------+------------+------+-----+---------+----------------+ 
| Field   | Type  | Null | Key | Default | Extra   | 
+-----------------+------------+------+-----+---------+----------------+ 
| id    | int(11) | NO | PRI | NULL | auto_increment | 
| role   | int(11) | NO |  | 1  |    | 
| username  | text  | NO |  | NULL |    | 
| password  | text  | NO |  | NULL |    | 
| email   | text  | NO |  | NULL |    | 
| phone   | text  | NO |  | NULL |    | 
| location  | text  | NO |  | NULL |    | 
| full_name  | text  | NO |  | NULL |    | 
| bio    | text  | NO |  | NULL |    | 
| website   | text  | NO |  | NULL |    | 
| last_login  | datetime | NO |  | NULL |    | 
| registered_date | datetime | NO |  | NULL |    | 
| registered_ip | text  | NO |  | NULL |    | 
| credits   | tinyint(1) | NO |  | NULL |    | 
| online   | int(11) | NO |  | 0  |    | 
+-----------------+------------+------+-----+---------+----------------+ 

cmw_blog(文章表)

+------------+----------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+------------+----------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| title  | text  | NO |  | NULL |    | 
| content | text  | NO |  | NULL |    | 
| date  | datetime | NO |  | NULL |    | 
| author  | int(11) | NO |  | NULL |    | 
| categories | text  | NO |  | NULL |    | 
| media  | text  | NO |  | NULL |    | 
| thumb  | text  | NO |  | NULL |    | 
+------------+----------+------+-----+---------+----------------+ 

cmw_projects(组合)

+-------------+------------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+-------------+------------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| owner_id | int(11) | NO |  | NULL |    | 
| title  | text  | NO |  | NULL |    | 
| content  | text  | NO |  | NULL |    | 
| date  | date  | NO |  | NULL |    | 
| link  | text  | NO |  | NULL |    | 
| img   | text  | NO |  | NULL |    | 
| type  | int(11) | NO |  | NULL |    | 
| start_date | date  | NO |  | NULL |    | 
| end_date | date  | NO |  | NULL |    | 
| done  | tinyint(1) | NO |  | 0  |    | 
| screenshots | text  | NO |  | NULL |    | 
+-------------+------------+------+-----+---------+----------------+ 

cmw_services(服务表)

+-------------+---------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+-------------+---------------+------+-----+---------+----------------+ 
| id   | int(11)  | NO | PRI | NULL | auto_increment | 
| cat_id  | int(11)  | NO |  | NULL |    | 
| name  | text   | NO |  | NULL |    | 
| description | text   | NO |  | NULL |    | 
| img   | text   | NO |  | NULL |    | 
| price  | decimal(11,2) | NO |  | NULL |    | 
+-------------+---------------+------+-----+---------+----------------+ 

在我的搜索,我需要在每一个name/title列,并在所有description/content列得来搜索字符串。很明显,我只想在一个查询中搜索所有这些表中的一个字符串。那可能吗?我知道使用JOIN,LEFT JOIN,RIGHT JOININNER JOIN可能很容易,但我不知道如何使用它们。谷歌对这些事情不是很明确!

+3

+1格式不错。 – Lion 2012-07-16 17:51:28

+0

使用连接很容易,但任何匹配都会返回所有4个表中的每一列。我不认为这是有意的行为。无论你的服务器有多慢,你都应该做4个查询或者重新构建你的数据库 – 2012-07-16 17:51:45

回答

4

四个连续查询的总成本很可能远低于JOIN的成本加上搜索这些相同记录/字段的成本。

如果有的话,检查FULLTEXT索引的可能性。

在任何情况下,你可以用的东西做到这一点像

SELECT "cmw_admin" as source, id FROM cmw_admin, NULL as date [...] WHERE bio LIKE '%search%' 
UNION 
SELECT "cmw_blog" as source, id FROM cmw_admin, date as date [...] WHERE 
    (title LIKE '%search%' OR content LIKE '%search%') 
UNION 
... 

,这将给你的发现记录列表,用记录从(“cmw_admin”,“cmw_blog来到那里有一丝在一起“,...);这将允许您选择如何呈现各种来源的记录。

查询将始终返回相同的一组字段,其中一些具有有效值,一些不是,具体取决于“源”是什么。然后在你的PHP脚本,你可以这样做,

$source = $record['source']; 
if (!isset($template[$source])) 
    $template[$source] = file_get_contents("templates/search/$source.html"); 

$html_view = preg_replace('#{{\s*([^}\s]*)\s*}}#e', 'isset(\$record["\1"])?\$vars["\1"]:""', $template[$source]); 

这将需要包含一个HTML片段的HTML模板像

<h2>{{ date }}</h2> 

和“填充”的字段的[日期]条目当前$记录。我发现这是保持HTML和代码分离的好方法(YMMV)。如果你已经有了一个模板系统,你可以(也应该)改编它。

+0

我如何做到这一点?我在MySQL非常新手,我知道基础和如何使用PRIMARY KEY,但'FULLTEXT'索引是另一件我不知道的... – 2012-07-16 17:55:09

1

如果只想在mysql中搜索,那么FULLTEXT索引就是要走的路。

在搜索时,你应该使用一个单一的查询PR表,因为你很可能需要建立联系/结果基于HTML的比赛在发现什么表,它是不同的。

但你应该考虑寻找到一个真正的像Apache Lucene这样的搜索引擎。Zend有一个非常好的实现,它不依赖于任何外部服务http://framework.zend.com/manual/en/zend.search.lucene.html/它可以帮助您比使用mysql更好地对结果进行排名,并且它应该更好地扩展。

+0

链接似乎没有被破坏,但很奇怪。我无法访问这些信息,它总是显示Zend Framework的介绍。 – 2012-07-16 17:59:39