CLucene - a C++ search engine http://sourceforge.net/projects/clucene/
傳統的全文檢索索引都是基於資料庫的,Sql Server Oracle mysql 都提供全文檢索索引,但這些比較大,不適合單機或小應用程式(Mysql4.0以上可以作為整合開發),Mysql也不支援中文。
後來得知Apache有一個開源的全文檢索索引引擎,而且應用比較廣,Lucene是Apache旗下的JAVA版的全文檢索索引引擎,效能相當出色,可惜是java版的,我一直在想有沒有C或C++版的,終於有一天在http://sourceforge.net 淘到一個好東東,Clucene!CLucene是C++版的全文檢索索引引擎,完全移植於Lucene,不過對中文支援不好,而且有很多的記憶體泄露,:P
Cluene不支援中文的分詞,我就寫了一個簡單的中文分詞,大概思路就是傳統的二分詞法,因為中文的分詞不像英文這類的語言,一遇到空格或標點就認為是一個詞的結束,所以就採用二分詞法,二分詞法就是例如:北京市,就切成 北京 , 京市。這樣一來詞庫就會很大,不過是一種簡單的分詞方法(過段時間我再介紹我對中文分詞的一些思路) ,當然了,在檢索時就不能輸入“北京市”了,這樣就檢索不到,只要輸入:“+北京 +京市”,就可以檢索到北京市了,雖然精度不是很高,但適合簡單的分詞,而且不怕會漏掉某些單詞。
我照著Clucene的分詞模組,做了一個ChineseTokenizer,這個模組就負責分詞工作了,我把主要的函數寫出來
ChineseTokenizer.cpp:
Token* ChineseTokenizer::next() {
while(!rd.Eos())
{
char_t ch = rd.GetNext();
if( isSpace((char_t)ch)!=0 )
{
continue;
}
// Read for Alpha-Nums and Chinese
if( isAlNum((char_t)ch)!=0 )
{
start = rd.Column();
return ReadChinese(ch);
}
}
return NULL;
}
Token* ChineseTokenizer::ReadChinese(const char_t prev)
{
bool isChinese = false;
StringBuffer str;
str.append(prev);
char_t ch = prev;
if(((char_t)ch>>8)&&(char_t)ch>=0xa0)
isChinese = true;
while(!rd.Eos() && isSpace((char_t)ch)==0 )
{
ch = rd.GetNext();
if(isAlNum((char_t)ch)!=0)
{
//是數學或英語就讀到下一個空格.或下一個漢字
//是漢字.就讀下一個漢字組成片語,或讀到空格或英文結束
if(isChinese)
{
//漢字,並且ch是漢字
if(((char_t)ch>>8)&&(char_t)ch>=0xa0)
{
// 返回上一個漢字
str.append(ch);
rd.UnGet();
// wprintf(_T("[%s]"),str);
return new Token(str.getBuffer(), start, rd.Column(), tokenImage[lucene::analysis::chinese::CHINESE] );
}
else
{
//是字母或數字或空格
rd.UnGet();
// wprintf(_T("[%s]"),str);
return new Token(str.getBuffer(), start, rd.Column(), tokenImage[lucene::analysis::chinese::CHINESE] );
}
}
else
{
//非漢字
// ch是漢字
if(((char_t)ch>>8)&&(char_t)ch>=0xa0)
{
// wprintf(_T("[%s]"),str);
rd.UnGet();
return new Token(str.getBuffer(), start, rd.Column(), tokenImage[lucene::analysis::chinese::CHINESE] );
}
str.append( ch );
}
}
}
// wprintf(_T("[%s]"),str);
return new Token(str.getBuffer(), start, rd.Column(), tokenImage[lucene::analysis::chinese::ALPHANUM] );
}
同時,這個中文分詞不支援檔案,只能支援記憶體流的形式,因為我用到了rd.UnGet();如果是檔案的話,嘿嘿,只能回退半個位元組哦
嗯。先寫到這裡了,今天太急了,等我有空了我就把我對CLucene的改進發到上面來。