天天看點

PHP+MYSQL實作全文檢索及全文檢索工具

使用分詞類庫,分詞類庫請參見: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