Posted on 2007-07-30 17:55
笨笨 閱讀(5398)
評(píng)論(10) 編輯 收藏 所屬分類:
Java
中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java)
最近在項(xiàng)目中面臨中文全文檢索的需求,關(guān)鍵需求如下:
1 支持中文、英文字詞的全文檢索,待檢索文本是古文言文。
2 全文檢索表達(dá)式支持: AND,OR,NOT,NEAR,BEFORE 運(yùn)算符,支持()。
3 速度要求:400M文本,要求在2-5秒內(nèi)能夠檢索完畢。
嘗試Lucene以及放棄原因:
在嘗試Lucene和不同的中文Analyzer后,終告放棄。
原因如下:
由于待檢索文本是古文,中文分詞技術(shù)無(wú)法派上用場(chǎng)。在將分隔存儲(chǔ)每個(gè)漢字后,發(fā)現(xiàn)從Lucene中檢索到的文本遠(yuǎn)遠(yuǎn)少于關(guān)鍵字實(shí)際匹配的文本,這一問題對(duì)于較長(zhǎng)的檢索關(guān)鍵字尤其明顯。
因?yàn)閷?duì)于檢索準(zhǔn)確程度要求很高,故此放棄,但是Lucene出的這個(gè)問題的原因尚不清楚,希望能夠有人提出解答。
自行實(shí)現(xiàn)中文全文檢索原理以及方法:
1 構(gòu)建過程,忽略標(biāo)點(diǎn)符號(hào),自行計(jì)算每個(gè)漢字在每個(gè)文本文件中的偏移量,并保存。
2 檢索過程,定位每個(gè)漢字的偏移量,如果檢索表達(dá)式中每個(gè)漢字的預(yù)期偏移量與實(shí)際偏移量吻合,則匹配成功。
3 采用 MappedByteBuffer 加快檢索速度,采用二分查找加快偏移量匹配速度,3個(gè)左右的關(guān)鍵字復(fù)合檢索能夠在1秒內(nèi)完成匹配(要求操作系統(tǒng)有足夠大的緩存)。
目前實(shí)現(xiàn)的一些局限和優(yōu)勢(shì):
0 中文檢索速度足夠,準(zhǔn)確度比Lucene高(如果有高手能夠解決這個(gè)問題,我會(huì)很高興的廢棄掉這些類的)
1 合適于中文,不適用英文文本
2 全文檢索索引文件與原始文本文件的大小大約為2:3-3:4之間,300M大小,比Lucene大約多30M。
3 索引文件的構(gòu)建時(shí)間長(zhǎng),400M大約需要3小時(shí),同時(shí)由于如果任何文本文件更新,都需要重新構(gòu)建索引文件,
因此不合適要經(jīng)常變化的文本索引。
全文檢索代碼示例(TestFullTextQuery.java):
File storeDir = new File("C:\\temp\\fulltext\\index");
StoreSearcher searcher = new StoreSearcher(storeDir);
String str = "大?藏 & 阿難"; //同時(shí)出現(xiàn) "大?藏" 和 "阿難", ?代表任意字符
searcher.queryBegin(str, true);
while(true){
StoreSearcherResult ssr = searcher.getNextQueryResult();
if ( ssr == null ){
break;
}
System.out.println("ID "+ssr.docId+":"+ssr.matchedCount);
}
searcher.queryEnd();
searcher.close();
運(yùn)行結(jié)果
ID T01n0001.TXT:320
ID T01n0002.TXT:3
ID T01n0004.TXT:2
ID T01n0005.TXT:202
ID T01n0006.TXT:131
....
附:全文檢索表達(dá)式舉例
關(guān)鍵字中間可以出現(xiàn)?,表明匹配任意字符。
運(yùn)算符名稱:運(yùn)算符字符
AND:&
OR:,
BEFORE:*
NEAR:+
NOT:-
表達(dá)式舉例:
(KEY1 <AND|OR|BEFORE|NEAR> KEY2) & (NOT KEY3)
KEY1 KEY2 (關(guān)鍵字之間無(wú)運(yùn)算符假設(shè)為AND)
附:全文檢索文件格式信息
DocInfoStore(文檔信息)
--HEAD--
DocCount:Integer 文檔數(shù)目
--DOC HEAD(PER DOC)--
DocSeq: Integer 文檔順序號(hào),內(nèi)部使用
DocId: Char[128] 文檔唯一ID,字符串格式
DocSepOfs: Integer 文檔分隔符數(shù)組的Ofs
--DOC SEP OFS(PER DOC)--
DocOfs: ArrayOfInteger 文檔分隔數(shù)組
WordInfoStore(每個(gè)漢字信息)
--HEAD--
WordCount:Integer 漢字?jǐn)?shù)
--WORD IDX(Per Word)--
WordChar:Integer 漢字的Unicode值
WordInfoOfs:Integer 漢字信息在文件中的偏移量
WordInfoSize:Integer 漢字信息大小
--WORD INFO(Per Word)--
DocCount: 漢字出現(xiàn)的文檔數(shù)
DocSeq(Per Doc): 每個(gè)文檔的順序號(hào)
WordInDocs:ArrayOfInteger 每個(gè)文檔中出現(xiàn)的漢字的偏移數(shù)組,從小到大排列
源文件及CLASS下載地址:
http://m.tkk7.com/Files/zhugf000/foreader2_ftsearch.zip
Feedback
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2007-07-31 08:52 by
看一下。。。。。。
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2007-07-31 10:33 by
用正則表達(dá)式啊
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java)[未登錄] 回復(fù) 更多評(píng)論
2007-07-31 10:59 by
說起來,Lucene的性能似乎不行啊(我沒測(cè)試過啊,只是網(wǎng)上資料說明)。似乎千萬(wàn)級(jí)別就比較慢了。前段日子用Lucene開發(fā)了個(gè)站內(nèi)搜索(數(shù)據(jù)量大概在幾百萬(wàn)吧),感覺無(wú)論是搜索(其實(shí)還好,在可接收范圍內(nèi))和索引都有點(diǎn)慢。有沒更好的實(shí)現(xiàn)啊?那些真正的能承受較大壓力的搜索都是怎么開發(fā)的?誰(shuí)知道?
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2007-07-31 14:59 by
都是的分布式的,索引和爬取基本上都是用的C++,WEB層用的是PHP,這是完美的結(jié)合!
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2007-07-31 17:08 by
這個(gè)有技術(shù)含量.
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java)[未登錄] 回復(fù) 更多評(píng)論
2007-08-01 14:12 by
笨笨啊,我有點(diǎn)迷茫。能給解答一下嗎?
公司的站內(nèi)搜索OK了,但領(lǐng)導(dǎo)讓我繼續(xù)研究研究搜索,但我不知道該繼續(xù)去研究什么好了。
中文分詞?目前使用的模塊(JE)還可以,如果自己研發(fā)需要不少時(shí)間,還有詞庫(kù)問題。
爬蟲?我們是站內(nèi)搜索,雖然頭說站外也是個(gè)方向,但很不明確,我對(duì)沒有明確需求的東西實(shí)在不感興趣。
分布式?目前的量還沒必要(幾百萬(wàn)),差的很遠(yuǎn)的,而且如果一直站內(nèi)搜索的話也很難用上。
緩沖?這個(gè)很有用,但目前實(shí)在沒有太好的想法。
目前站內(nèi)搜索的狀況就是正常運(yùn)行,沒什么錯(cuò)誤,也不知道該改些什么。很迷茫。(還有個(gè)項(xiàng)目相反,能正常運(yùn)行,但我還有很多想法,但領(lǐng)導(dǎo)說我在那個(gè)項(xiàng)目浪費(fèi)太多時(shí)間了,不許我再做了,能運(yùn)行就行。-_-!)
最近很怪,我對(duì)搜索的研究很迷茫,對(duì)用戶的需求倒是很感興趣。我一直在思考自己的東西最終能給用戶帶來什么,如何讓用戶更加方便的使用。
嗯。。。就是很迷茫,有啥好的建議嗎?
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2007-08-02 14:04 by
用lucene檢索的時(shí)候,結(jié)果少的原因,應(yīng)該是,你查詢的時(shí)候用的分詞器不對(duì)。
在查詢之前先把每個(gè)字直接加一個(gè)空格。例如:“中文檢索”-》“中 文 檢 索”。
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2008-06-18 15:40 by
很好的東西啊 呵呵 可惜缺少些jar
能不能送我啊 litao1258@126.com
多謝
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2008-07-01 15:12 by
東西已經(jīng)收到,不勝感激!
# re: 中文全文檢索的實(shí)現(xiàn)以及一些經(jīng)驗(yàn)(Java) 回復(fù) 更多評(píng)論
2008-08-11 11:46 by
你好,笨笨,我剛剛研究lucene,現(xiàn)在面臨的問題也是中文的全文檢索,
我的問題正好和你相反,我返回的數(shù)據(jù)太多了。
比如搜索的keyword是[高考]會(huì)被拆分為[高][考]兩個(gè)字進(jìn)行檢索。
這樣的話檢索大量數(shù)據(jù)的時(shí)候就會(huì)很慢,而且我做了關(guān)鍵字的高亮顯示
這樣一來,比如標(biāo)題為【2008年北京考區(qū)高考狀元】那么被高亮后為
2008年北京[考]區(qū)[高][考]狀元,這樣看起來很不好,怎么樣可以按著【詞】來
建立索引呢,然后按著【詞】進(jìn)行檢索并高亮,頭疼的問題,可以和您討論一下嘛?
其他的朋友也歡迎討論。希望您能聯(lián)系我一下,QQ396615834 MSN wind_1121@hotmail.com 十分感謝。