星期六, 11月 19, 2005

MySQL 也支援全文檢索

要提供一套查詢、檢索文件的系統,「全文檢索」(full-text retrieval;使用者輸入 query 字串,系統會把這個字串與文件的全文字串做比對,來找出符合 query 的文件們) 已經是不可或缺的要角了。

沒有人會質疑 Google 搜尋引擎的威力吧。事實上,Google 搜尋引擎做得最好的,就是能針對使用者下的 full-text query,在極短時間內,從非常大量的網路文件庫中,找出(並排序)「最有可能滿足使用者 query」的文件(URL、摘要、以及庫存檔)。

而實驗室既然想做一套「古契書的檢索系統」,當然也得提供全文檢索的功能。不過,現實面上,很容易就會處於抉擇的難點。難以抉擇的地方在哪兒呢?原來,我們的系統,並不只是想提供全文檢索,還希望利用其他的 metadata(好像是翻譯為「詮釋資料」吧)來增進檢索的效能。

於是,系統可能就得整合一套關連式資料庫 (RDDB)、與一套全文檢索系統(例如,Apache 的 Lucene project)。「整合」總是件吃力卻不怎麼討好的工作。

雖然 Microsoft SQL Server 很早就有同時提供 RDDB 與 full-text retrieval 的功能,但是實驗室老闆是很討厭 M$ 的;Oracle 有很好的 RDDB,但全文索引不是內建;因此,腦筋通常都會動到開放原始碼的 MySQL 上。

很高興地看見,MySQL 文件上,說它是支援全文檢索的。不過,實際跑了跑,就會有些沮喪:對中文資料而言,似乎行不通。手冊、甚至是網路文件上,對於如何處理中文的全文檢索,雖有片段的說明,卻缺乏完整的實例。

好吧,這又是一個需要做實驗(測試、並嘗試找到解答)的地方。「實驗室」嘛,就是得做做實驗,不是嗎?

透過以下這些步驟,應該可以讓 MySQL 處理中文的全文檢索:
  1. 資料庫採用 UTF-8 編碼格式,以支援中文。此外,欲提供全文檢索,資料表必須採用 MyISAM 的型態。例如,CREATE TABLE table_name (...) ENGINE=MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
  2. 在資料表內建立欄位的全文索引。由於 MySQL 並不支援中文的斷字,因此我們目前還得新增一個欄位來儲存輔助全文檢索。例如,假設我們想對 DOC 欄位做全文索引,那麼除了 DOC 之外,我們還得新增一個(名稱自取的)DOC_FOR_FULLTEXT 欄位。然後,在 CREATE TABLE 時,加入 FULLTEXT (DOC_FOR_FULLTEXT) 來對這個輔助欄位的資料,建立全文索引。
  3. 將全文資料填入 DOC 欄位時,也將「自行斷字處理後的文件字串」填到 DOC_FOR_FULLTEXT 欄位裡。例如,假設要填入 DOC 欄位的全文是"新竹縣東興庄",那我們也同時將斷字後的 "新 竹 縣 東 興 庄 "(註:若字串內容為 UTF-16 Little Endian 編碼,利用 PHP 的 chunk_split() 可以在字串內,每隔兩個 bytes 插入一個空白字元 "\x20\0")填入 DOC_FOR_FULLTEXT 欄位。
讓 MySQL 提供全文索引後,接下來是處理使用者輸入字串的部分:
  1. 執行 full-text SQL query 前,先執行 SET NAMES 'utf8'
  2. full-text SQL query 長得像這副模樣: SELECT * FROM WHERE MATCH (DOC_FOR_FULLTEXT) AGAINST ($fulltext_query IN BOOLEAN MODE)。其中,$fulltext_query 是一個對 user query 做過處理的字串。例如,若使用者輸入「新竹」,則 $fulltext_query 需要被處理為「'"新 竹"'」(注意:「新」與「竹」之間要有空白斷開,「新 竹」要用單引號框住雙引號;還有,不要忘記,SQL query 必須以 UTF-8 編碼的)。

4 則留言:

被掛掉的阿尼 提到...

用英文的檢索來檢索中文是有許多阿里不達的小麻煩的...而且還有近似搜尋的問題....還有詞的問題, 中研院的斷詞詞庫"應該"沒包括古契書的詞....
反正, 剛開始的時候, 一定是撈到一票不要的東西, 還要多一次處理來過濾, 接下來就是針對過濾的部份來增加資料庫的欄位....

tu 提到...

哈哈,「用英文的檢索來檢索中文是有許多阿里不達的小麻煩的」,說得真夠貼切。

不過,有這麼多麻煩,那要不要自己開發中文的檢索系統?嗯... 這需要有「非常強大」的後援,我看還是算了吧。

想到 MPH 說:「現在這個年紀,唉,算了吧,正事要緊」還真是感慨良多~

被掛掉的阿尼 提到...

呵, 很多人做過這樣的努力, 但都失敗了. 原因之一, 基本的功能可能都比不上 google...原因之二, 很多麻煩是扯到特定的需求, 例如你可能會有名詞演變的問題(例如 基隆雞籠, 但不是同音的問題).
所以找一個全文檢索配合資料庫是個不錯的做法, 雖然時間不見得比較快, 可是看得到未來的路...我現在比較感興趣的是google desktop....

YingChih Fang 提到...

1.請問斷字 DOC_FOR_FULLTEXT
的意思是要把每個中文字 都拆解成一個一個單字嗎?

2.搜尋時 也將搜尋字 拆解成一個一個單字?