如何使用PHP實現全文檢索索引功能?
很多人可能馬上可以想出幾種方案,比如:檔案檢索法、採用SQL的like語句等方法,但這些方法效率都相當的低。
這裡介紹一種比較高效的PHP全文檢索索引實現方法,這就是採用MYSQL的FULLTEXT欄位類型。但是MYSQL的FULLTEXT欄位對中文的支援不是很好,本文也一併介紹如何通過PHP+MYSQL實現中文全文檢索索引功能。
首先需要用到一個PHP中文分詞擴充模組??SCWS,關於這個模組的安裝和使用大家可以到www.ftphp.com/scws去尋找相關內容(如有問題請留言)。
然後再看看mysql的fulltext欄位類型的相關資訊:
MySQL3.23.23之後的版本開始支援全文索引和搜尋。全文索引在 MySQL 中是一個 FULLTEXT 類型索引。
FULLTEXT 索引用於 MyISAM 表,可以在 CREATE TABLE 時或之後使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、VARCHAR 或 TEXT 列上建立。對於大的資料庫,將資料裝載到一個沒有 FULLTEXT 索引的表中,然後再使用 ALTER TABLE (或 CREATE INDEX) 建立索引,這將是非常快的。將資料裝載到一個已經有 FULLTEXT 索引的表中,將是非常慢的。
MYSQL全文檢索搜尋通過 MATCH() 函數完成。
下面舉一簡單例子:
1、建立資料表:
CREATE TABLE fulltext_sample(copy TEXT,FULLTEXT(copy)) TYPE=MyISAM;
這裡的copy就是一個fulltext類型的欄位,如果建表的時候沒有添加全文檢索索引欄位,也可以通過alert來添加,如:
ALTER TABLE fulltext_sample ADD FULLTEXT(copy)
2、插入資料:
INSERT INTO fulltext_sample VALUES('It appears good from here'),('The here and the past'),('Why are we hear'),('An all-out alert'),('All you need is love'),('A good alert');
3、資料檢索:
SELECT * FROM fulltext_sample WHERE MATCH(copy) AGAINST('love');
上面就是mysql的全文檢索索引功能,注意:在全文索引上進行搜尋是不區分大小寫。
下面再看如何?中文全文檢索索引。
fulltext欄位是以詞語為單位,詞語之間需要用空格隔開,而漢語的句子中各個詞語之間並不會用空格隔開,因此我們需要對中文進行分詞,這也就是為什麼上面需要強詞用到中文分詞擴充模組。
但是儘管對中文進行分詞,MYSQL還是不能通過MATCH來實現中文的全文檢索索引,這需要通過一定的方法來進行轉換,一個比較簡單實用的方法是採用下面這個函數(當然還有更好的),它將中文進行了urlencode轉換。
function q_encode($str){$data = array_filter(explode(" ",$str));$data = array_flip(array_flip($data));foreach ($data as $ss) { if (strlen($ss)>1 ) $data_code .= str_replace("%","",urlencode($ss)) . " ";}$data_code = trim($data_code);return $data_code;}
將轉換過後的內容儲存至事先定義好的fulltext欄位。同樣,在查詢的時候也需要將查詢的關鍵詞進行同樣方法的轉換。
PHP+Mysql實現UTF8全文檢索搜尋的方法
本文講解一下如何在海量的資料中能夠快速的進行全文檢索索引呢?MySQL提供了一個全文索引功能,也就是把欄位設定上FULLTEXT索引屬性,然後通過SELECT的MATCH AGAINST語句進行尋找。
我們開發的一個純英文網站TouchUs - The Global Yellow Pages & Business Directory(www.touchus.org)就是利用MySQL的這一功能,實現了對十多萬條資料的平均全文檢索索引時間小於0.5秒。但是在開發TouchUs的中文網站??城市黃頁網時(www.city39.cn),碰到了新的問題。原來英文排版時詞和詞之間是通過空格區分的,FULLText可以完全支援,但是對中文或者是東亞文字就沒有這麼簡單了,因為中文的詞和詞之間並沒有明顯的分隔,所以MySQL不支援中文字元的全文檢索索引。
如何讓MySQL也能支援中文的全文檢索索引呢?偶然間產生了一個思路,那就是能不能在中文分詞後,通過對中文進行編碼轉化成英文字元,這樣就在中英文間建立一個特定的聯絡,然後再進行全文檢索索引,這樣不就實現了中文的全文索引了嗎?經過實驗,答案是肯定的。下面是在城市黃頁網中實現的具體過程:
1. 建立一個單獨的索引表,比如對應members表,我們建立一個members_index表。
使用者資訊表(members) 使用者資訊全文索引表(members_index)
User_id user_id
User_name index_intro
User_introduction
在members_index表的index_intro中加入fulltext索引。
2. 對使用者資訊表(members)的User_introduction欄位內容進行中文分詞處理
中文分詞的處理過程,可以參考簡易中文分詞系統http://www.ftphp.com/scws/,在城市黃頁網中,我們採用了scws的PHP擴充模組方式來實現中文分詞。scws的php擴充模組安裝非常簡單,只需簡單編譯配置後即可使用。在具體的php代碼中,我們寫了如下的函數來實現分詞後將分詞結果用空格進行串連。
//中文分詞函數function str_fc($str) {$so = scws_new();$so->set_charset('utf8');// 這裡沒有調用 set_dict 和 set_rule 系統會自動試調用 ini 中指定路徑下的詞典和規則檔案$so->send_text($str);while ($tmp = $so->get_result()){foreach ( $tmp as $ss ){$s = trim($ss[word]);if ( $s )$mystr .= trim($ss[word]) . " ";//echo urlencode(trim($ss[word])) . " ";}}return $mystr;}
該函數返回就是用空格串連的分詞結果。
3. 對分詞結果進行編碼,可以採用多種編碼方式,比如base64編碼、urlencode編碼、漢字轉拼音等,對gb2312甚至可以採用區位碼編碼方式。考慮到儲存空間以及便利性,我們採用了PHP的urlencode編碼方式。需要注意的是,在編碼前,我們可以去掉重複的分詞來節約儲存空間,編碼後要去掉編碼結果中的%符號,因為urlencode採用RFC 1738???行編碼,會產生很多%,而%在MySQL是萬用字元。下面是編碼過程用到的PHP代碼
$data = str_fc($data); //中文分詞$data = array_filter(explode(" ",$data)); //刪除數組空項$data = array_flip(array_flip($data)); //重複資料刪除項//對分詞結果進行urlcode編碼foreach ( $data as $ss ) {if (strlen($ss)>1 )$data_code .= str_replace("%","",urlencode($ss)) . " ";}
這裡的$data_code就是編碼後的結果。把編碼結果根據user_id存入使用者資訊全文索
引表(members_index)
4. 在進行搜尋處理時,首先對使用者輸入的關鍵字進行同樣的分詞編碼處理,然後通過MySQL的SELECT的MATCH AGAINST語句進行全文快速檢索,根據檢索結的user_id即可調用使用者資訊表(members)中的未經處理資料進行顯示,而沒有必要進行一次解碼重組。
以上MySQL UTF8中文全文檢索索引方法.