使用分詞類庫,分詞類庫請參見:http://www.xunsearch.com/scws/
如何使用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中文全文檢索方法.
全文檢索工具:http://www.xunsearch.com