這幾天總算是比較接近完成的階段了,在問過 far 之後來寫一篇講一下。
大約是在年初的時候 far 就想要將 Pixnet Blog 的部份弄 Fulltext Search,剛好那陣子我也在弄類似的東西,survey 一些對 CJK 支援比較好的 Fulltext Search Engine,當時看起來比較好用是 平林幹雄 維護的 HyperEstraier。(我也寫了 HyperEstraier 與 HyperEstraier 與 qdbm 的一些雜記 兩篇文章)
不過後來 HyperEstraier 將近三個月沒更新,加上 Pixnet 那陣子在忙公司整合的事情,所以這件事情在收了訂金後就一直擱著... (皇上都不急了,太監就不要在旁邊跳腳...)
除了 HyperEstraier 外,我還有訂另外幾個 Fulltext Search Engine 的 mailing list,其中 Gmane 用的 Xapian 也蠻值得關注的。我從 0.9.x 版的時候就在觀察,當時連 UTF8 support 都沒有,但是 Gmane 有丟出 3rd party patch。不過我寫信去問 Gmane 得到的回答是,文章數量很大,但是每天搜尋的人次並不多,平均不到 1 query/sec。(信件在 /var/mail/gslin,隨著硬碟爛掉沒備份到消失了,只能憑映象寫...)
再加上 Gmane 以英文為主,當時沒有很仔細繼續去研究,直到後來在 Xapian 的 mailing list 上看到有對岸的人說中文的部份他用的很好,仔細去研究以後發現其實是因為以前想的太複雜,加上對 Xapian 不熟造成的誤解而沒有仔細去研究 Xapian 的細節。
所以... 以下進入 Xapian 的細節。
Xapian 的每一份文件 (Document) 分成三個部份,文件主體 (Data)、值 (Value)、項目 (Term)。Data 是一組字串,通常就是放文章內容,但是也可以不用放。Value 是 key+value 的集合,key 的部份是數字,而 value 的部份則是一個字串,Value 可以用很多組。(這邊的 "value" 並不是遞迴定義,而只是官方取的名字剛好就是 Value)
不過上面那兩項都是插花用的,重點在 Term。一個 Term 是一個帶有 weight 的字串,會被 Xapian 索引。所以你可以對 Term 下搜尋條件,Xapian 會傳回符合的項目。
對英文來說,假設我要索引 "A apple a day keeps the doctor away." 這個句子,那麼我只要以非英文字的部份切開就可以了,換句話說,最簡單的情況會被切成:['a', 'apple', 'a', 'day', 'keeps', 'the', 'doctor', 'away'],另外內建常用字的詞庫把一些比較沒有意義的詞濾掉,於是 a、the 就會被濾掉變成:['apple', 'day', 'keeps', 'doctor', 'away'],然後再進一步對詞性做處理,於是把 keeps 轉成 keep,最後索引成:['apple', 'day', 'keep', 'doctor', 'away']。
對中文來說 (以及日文、韓文),假設我要索引「端午假期16日、20日兩次夜間暫停收費」這個句子,以單字一個一個切開,切成 ['端', '午', '假', '期', '16', '日', '20', '日', '兩', '次', '夜', '間', '暫', '停', '收', '費'],或是兩個字兩個字切,切成 ['端午', '午假', '假期', '期16', '16日', '20日', '日兩', '兩次', '次夜', '夜間', '間暫', '暫停', '停收', '收費'] 似乎都不太好,前者當搜尋條件很少的時候準確度不太高 (像是以「林洋港」為條件搜尋時可能會找到討論海港旁邊樹林的文章),而後者則會收了不少沒有意義的字,像是 '期16', '日兩', '間暫',而且像是 '次夜' 其實不是這句的應該有的意思。
所以對於 CJK 的斷詞演算法來說,能夠切出符合的 Term 才是重點,於是就有很多論文在討論這些方法... 不過很多方法都是建立在詞頻表上面,換句話說,詞頻表的正確性會影響到搜尋的品質,而為了確保詞頻表的正確性,有很多時候必須讓人力去介入,這點我跟 far 都不太喜歡,我們偏好的是即使不去管,也保持一定的水準的方法。
所以我跟 far 解釋完以後,決定用一字表 + 兩字表硬切產生所有的 Term (也就是上面兩組都取來當 Term),然後看看效果如何。在跑了二十幾個小時將全站所有文章掃過一次後內部測試 (目前最新文章的 id 是 528xxxx,實際的數字當然比這個少,不過 far 說這是商業機密不能公開 XD),far 對於搜尋出來的品質還蠻滿意的,所以就切到兩個字... (如果 far 不滿意的話我打算再把三個字的切詞加上去 XD)
然後用 Catalyst 兜個 HTTP API 出來讓前端的 Web 用,其實就很棒了 :p (我知道有 xapian-tcpsrv,不過...)
所以大概就是這樣啦,Pixnet Blog 的 Fulltext Search 應該有機會在七月底前看到吧?(因為 far 很墮落,所以我實在不能保證六月底前出的來... XD)
太好了﹐這兩天都未吃明白 bbs 上有關 xapian 的東西﹐現在你把入門資料整理出來﹐我總算有了點印象。七月起我也有 project 需要做 CJKV 的資料挖掘﹐到底再深究一下。
謝謝報告!//bow
為什麼不用 Lucene 呢? 這類的 CJKV bigram 功能早就有了。
沒有... 被提起來才發現完全沒有想到要用Lucene...
中文斷詞的部分可以參考一下中研院的CKIP。
中研究的很常斷線…
不知道還有沒有其它的方案
Hello, gslin.
我最近也在构建一个小型站内全文搜索引擎,正好也找到 xapian,顺路从 Google 走到了您的 Blog 。
您是 BBS 上的 DarkKiller 大大吧,能否给MSN或email的交流方式呀,有些相关的问题还想向您请教。
此外,我已经有做出一个简易的中文分词系统(支持 GBK/BIG5/UTF-8编码),纯C编写,如果有可能我想在 xapian 中使用它。(http://www.hightman.cn/demo/scws/v4.php 可测试)
由于刚接触 xapian 很不熟悉,还请不吝指教,十分感谢!
既然您有看 BBS 的話,在我個人板上聊就可以了...