我愛我的家園!

          成功在于你是否努力,希望在于你是否相信自己!

           

          基于Lucene/XML的站內(nèi)全文檢索解決方案:WebLucene

          內(nèi)容摘要:
          為Lucene做一個通用XML接口一直是我最大的心愿:更方便的在WEB應(yīng)用中嵌入全文檢索功能

          • 提供了XML的數(shù)據(jù)輸入接口:適合將原有基于各種數(shù)據(jù)庫的數(shù)據(jù)源導(dǎo)入到全文索引中,保證了數(shù)據(jù)源的平臺無關(guān)性;
          • 通過了基于XML的搜索結(jié)果輸出:方便了通過XSLT進行前臺的結(jié)果顯示;
          								
          MySQL \ / JSP
          Oracle - DB - ==> XML ==> (Lucene Index) ==> XML - ASP
          MSSQL / - PHP
          MS Word / \ / XHTML
          PDF / =XSLT=> - TEXT
          \ XML
          \_________WebLucene__________/
          使用過程如下:
          1. 將數(shù)據(jù)用腳本導(dǎo)出成XML格式;
          2. 將XML數(shù)據(jù)源導(dǎo)入LUCENE索引;
          3. 從WEB界面得到XML結(jié)果輸出,并通過XSLT生成HTML頁面

          站內(nèi)全文檢索的必要性

          雖然大型搜索引擎的功能已經(jīng)越來越強大了,很多站點都使用了Google的站內(nèi)檢索site:domain.com代替了自己的站內(nèi)數(shù)據(jù)庫“全文”檢索。 但依靠GOOGLE這樣的大型搜索引擎做站內(nèi)檢索會有以下弊端:
          • 數(shù)量有限:搜索引擎并不會深度遍歷一個網(wǎng)站,而將網(wǎng)站所有的內(nèi)容都索引進去,比如Google就喜歡靜態(tài)網(wǎng)頁,而且是最新更新的,而不喜歡帶?的動態(tài)網(wǎng)頁,Google甚至?xí)ㄆ趯⑷鄙偃肟诘木W(wǎng)站內(nèi)容逐漸拋棄;
          • 更新慢:搜索引擎針對站點的更新頻率也是有一定周期的,很多內(nèi)容需要一定時間后才能進入GOOGLE的索引:目前Google Dance的周期是21天左右;
          • 內(nèi)容不精確:搜索引擎需要通過頁面內(nèi)容提取技術(shù)將導(dǎo)航條,頁頭頁尾等內(nèi)容過濾掉,反而不如直接從后臺數(shù)據(jù)庫提取數(shù)據(jù)來得直接,這種摘要和排重機制是很難實現(xiàn)的;
          • 無法控制輸出:也許有更多的輸出需求,按時間排序,按價格,按點擊量,按類目過濾等

          系統(tǒng)的搭建

          下載:
          http://sourceforge.net/projects/weblucene/

          XML數(shù)據(jù)源的導(dǎo)入:

          只要數(shù)據(jù)源可以導(dǎo)出成3層的XML結(jié)構(gòu),就都可以用IndexRunner這個命令行工具導(dǎo)入:

          比如從數(shù)據(jù)庫導(dǎo)出:news_dump.xml
          <?xml version="1.0" encoding="GB2312"?>
          <Table>
          ??? <Record>
          ??? ??? <Title>標(biāo)題</Title>
          ??? ??? <Author>作者</Author>
          ??? ??? <Content>內(nèi)容</Content>
          ??? ??? <PubTime>2003-06-29</PubTime>??? ??
          ??? </Record>
          ??? <Record>
          ??? ??? <Title>My Title</Title>
          ??? ??? <Author>chedong</Author>
          ??? ??? <Content>abc</Content>
          ??? ??? <PubTime>2003-06-30</PubTime>
          ??? </Record>
          ??? ...
          </Table>

          IndexRunner -i news_dump.xml -o c:\index -t Title,Content -n Author
          -i news_dump.xml:? 以news_dump.xml為數(shù)據(jù)源
          -o c:\index?? 索引庫建立在c:\index目錄下
          索引建立Title Author Content PubTime這幾個字段外,按以下規(guī)則建立索引:
          -t Title,Content 一個進行分詞的全文索引TokenIndex:數(shù)據(jù)是Title Content這2個字段
          -n Author??? 一個不分詞的索引:NoTokenIndex:數(shù)據(jù)源是Author這個字段。

          對于RSS數(shù)據(jù)源:
          <?xml version="1.0"?>
          <rss version="0.92">
          <channel>
          ? <title>Amazon: Books Arts &amp; Photography</title>
          ? <link>http://www.lockergnome.com/</link>
          ? <description>Amazon RSS Feed</description>
          ? <lastBuildDate>Sun, 29 Jun 2003 01:05:01 GMT</lastBuildDate>
          ? <docs>http://www.lockergnome.com/</docs>
          ? <webMaster>amazonfeed@lockergnome.com (Lockergnome RSS Generator)</webMaster>
          ? <item>
          ??? <title>The Artist's Way: A Spiritual Path to Higher Creativity - $11.17</title>
          ??? <link>http://www.amazon.com/exec/obidos/ASIN/1585421464/lockergnomedigit/?ref=nosim&amp;dev-it=D34HUVGKB34YFX</link>
          ??? <description>http://www.lockergnome.com/??? </description>
          ? </item>
          ? ...
          </channel>

          IndexRunner -i http://www.example.com/rss.xml -o c:\index -t title,description -n link? -l? 4
          -l 4 表示拿第4層節(jié)點作為字段映射,

          IndexRunner還提供了-a -m這兩個選項:用于增量索引和批量索引優(yōu)化。
          -a? 增量索引,表示在原有索引的基礎(chǔ)上擴展
          -m? mergeFactor 在Lucene中mergeFactor是一個針對批量索引的優(yōu)化參數(shù),控制多少條處理完多少條記錄(Document)后,寫入一次索引,寫入頻率越高,內(nèi)存使用越少,但索引速度越慢,所以在大批量數(shù)據(jù)導(dǎo)入時需要增大文件寫入的間隔,多讓索引在內(nèi)存中操作。

          搜索結(jié)果輸出:


          以下是系統(tǒng)設(shè)計過程中一些設(shè)計的思路:

          做為工業(yè)標(biāo)準(zhǔn)的XML

          記得以前有關(guān)于肯德基的炸薯條斷頓的報道。從這個事件報道中我們可以看到一種更高效的管理體系:對于快餐店這樣全球性的企業(yè)來說,要保證各地提供的薯條品質(zhì),成本最低的方法肯定是依靠機器而不是廚師,如果要求薯條機能夠處理各種形狀不一的土豆,機器的復(fù)雜程度和維護成本都會很高。所以土豆必須嚴格符合工業(yè)標(biāo)準(zhǔn)才能讓結(jié)構(gòu)比較簡單的薯條機生產(chǎn)出符合標(biāo)準(zhǔn)的薯條,因此,薯條的加工機械會嚴格按照土豆協(xié)會的土豆工業(yè)標(biāo)準(zhǔn)設(shè)計。高質(zhì)量的原料可以大大降低后期加工設(shè)備的成本,因此從總體成本上講還是合算的。

          對于軟件應(yīng)用開發(fā)者來說:應(yīng)用和應(yīng)用之間,企業(yè)和企業(yè)之間交換的數(shù)據(jù)好比就是土豆,白菜,按照嚴格的XML標(biāo)準(zhǔn)設(shè)計的接口作為企業(yè)之間后臺數(shù)據(jù)交換的工業(yè)標(biāo)準(zhǔn),雖然不如簡單的CSV格式高效,但缺能大大簡化下游工序的后期加工成本。

          不難想象為什么處理HTML的瀏覽器:IE和Mozilla等瀏覽器軟件大小都在10M以上,但一般處理XML的解析器一般都在幾百K。除了沒有界面外,HTML瀏覽器需要為太多不規(guī)范的HTML代碼提供大量容錯處理也是一個很重要的原因,而語法嚴格,規(guī)則簡單的XML處理器就可以做的很簡短,高效,體積越“小”就意味著適應(yīng)性越廣:這點在手機這樣的硬件配置比較低的設(shè)備環(huán)境中顯得尤其重要。

          雖然XML在后臺數(shù)據(jù)交換方面,有著巨大的潛力。在前臺表現(xiàn)方面,XML并不會馬上代替HTML,很多通過XSLT輸出的HTML仍然需要結(jié)合CSS來進行表現(xiàn)。XML ==XSLT==> HTML + CSS。但是由于太多的網(wǎng)頁都是用HTML做的,相信XML沒有必要馬上代替這些已有的機制。

          此外在應(yīng)用的國際化支持方面XML和Java簡直是絕配:XML數(shù)據(jù)源用Java解析后是UNICODE,這樣無論是日文,繁體中文還是德文的內(nèi)容我們都可以在一個索引庫中同時進行搜索。這樣針對其他語言的支持只是設(shè)計各種語言界面的問題了。

                GBK          \                                       / BIG5
          BIG5 - UNICODE ====> Unicode - GB2312
          SJIS - (XML) (XML) - SJIS
          ISO-8859-1 / \ ISO-8859-1
          使用XML的另外一個額外好處在于:開發(fā)人員一般都沒有仔細理解Java的字符集(其實上是JVM的缺省file.encoding屬性)受系統(tǒng)本地化設(shè)置的影響,基于XML的輸入使得數(shù)據(jù)的字符解碼過程變得透明:不用再和用戶解釋需要如何解碼,編碼數(shù)據(jù)源。不過,XML的學(xué)習(xí)成本還是比較高的,假設(shè)你HTML的學(xué)習(xí)成本是1,XML則可能為10,而XSLT的學(xué)習(xí)成本則可能高達100。

          傳統(tǒng)數(shù)據(jù)庫應(yīng)用的全文檢索加速

          讓數(shù)據(jù)庫負責(zé)精確匹配,將模糊匹配用獨立的系統(tǒng)實現(xiàn)

          一個站點內(nèi)容積累在萬級以上,站內(nèi)全文檢索就會是用戶定位最主要的手段,而關(guān)鍵詞檢索是用戶最熟悉的方法。因此基于數(shù)據(jù)庫的傳統(tǒng)WEB應(yīng)用在全文檢索需求還是很大的。

          但是可怕的%like%數(shù)據(jù)庫操作可能會吃掉數(shù)據(jù)庫服務(wù)器90%以上的CPU。Oracle MSSQL等數(shù)據(jù)庫服務(wù)器中數(shù)據(jù)庫內(nèi)置的全文檢索基本上都不太適合WEB應(yīng)用。而數(shù)據(jù)庫另外一個的弊端在于對于條件簡單的查詢返回結(jié)果集非常大:數(shù)據(jù)庫并不知道如何面向用戶最關(guān)心的的頭100條結(jié)果進行優(yōu)化。根據(jù)以前的統(tǒng)計:頭100條結(jié)果往往已經(jīng)可以滿足95%以上用戶需求。

          需要緩存設(shè)計:根據(jù)我們的經(jīng)驗,在應(yīng)用設(shè)計中沒有必要進行內(nèi)置的結(jié)果緩存設(shè)計:讓前臺的應(yīng)用服務(wù)器內(nèi)置的緩存機制或者反相代理緩存服務(wù)器進行緩存就夠了。

          數(shù)據(jù)同步策略

          總體上講,全文檢索和數(shù)據(jù)庫其實是2種根本不同的應(yīng)用模式,全文檢索系統(tǒng)其實往往也沒有必要和數(shù)據(jù)庫那么高的實時同步機制,如果按照:低更新,高緩存的模式進行設(shè)計:數(shù)據(jù)庫數(shù)據(jù)到全文索引的同步過程一般都可以通過腳本定期將數(shù)據(jù)庫的數(shù)據(jù)導(dǎo)出成XML,然后進入Lucene的全文索引。而針對原有數(shù)據(jù)記錄的更新和刪除,其實一般可以通過定期的重建索引解決。WebLucene其中索引部分是一個IndexRunner的命令行程序?qū)崿F(xiàn)的。

          結(jié)果排序策略

          站內(nèi)全文索引另外一個很重要的需求是可定制的排序:按時間,按價格,按點擊量……Lucene全文索引缺省只提供了根據(jù)關(guān)鍵詞在原文中的匹配度排序,而任何根據(jù)某個字段的值進行排序的都無法避免再次遍歷數(shù)據(jù),從而導(dǎo)致性能有數(shù)量級的下降(等于又是做%Like%檢索),而在索引中,除了匹配度SCORE外,唯一能用來排序的就是索引記錄的ID,所以一個比較高效率實現(xiàn)定制排序的方法時:在索引時,讓進入Lucene全文的順序?qū)?yīng)著一定規(guī)則:比如時間,然后在搜索時,讓搜索結(jié)果按照索引記錄的ID進行排序(或倒排)。

          搜索結(jié)果關(guān)鍵詞標(biāo)引的實現(xiàn)

          搜索結(jié)果中關(guān)鍵詞通過紅色或者黑體字標(biāo)記出來,為了能夠更恰當(dāng)?shù)娘@示相關(guān)上下文的問題,標(biāo)引是通過限制了一個掃描范圍,然后根據(jù)一個分析器將指定的詞流式的讀取出來,然后

          全文檢索和其他應(yīng)用的集成

          其實核心的是一個Lucene的XML接口:SAX方式的數(shù)據(jù)導(dǎo)入和DOM方式的結(jié)果輸出。

          XML的數(shù)據(jù)源定義:
          只要是能夠映射成表=》記錄=》字段這樣層次結(jié)構(gòu)的都可以。因此WebLucene索引的設(shè)計比較靈活,甚至可以直接用來索引RSS。

          XML結(jié)果定義:參考了Google的XML接口的設(shè)計

          如果沒有SERVLET界面,提供XML輸出的DOMSearcher也可以很方便集成到各種應(yīng)用系統(tǒng)中。

          參考資料:

          系統(tǒng)設(shè)計中使用的一些模塊:

          其他開發(fā)人員的一些反饋和改進

          原帖:?

          posted on 2007-09-30 12:29 死神 閱讀(269) 評論(0)  編輯  收藏 所屬分類: 新思路


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           

          導(dǎo)航

          統(tǒng)計

          公告

          歡迎大家來到我的個人世界!

          常用鏈接

          留言簿(3)

          隨筆分類(5)

          隨筆檔案(9)

          文章分類(37)

          文章檔案(41)

          相冊

          語音技術(shù)

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 潞西市| 佛冈县| 思南县| 喜德县| 开封市| 界首市| 凉城县| 灵武市| 星座| 大田县| 湖州市| 三穗县| 榆中县| 玉田县| 泾源县| 北海市| 宁津县| 永安市| 临汾市| 兰州市| 郑州市| 寿阳县| 麻阳| 沈丘县| 武川县| 金川县| 平遥县| 湖北省| 康保县| 明溪县| 安龙县| 杭锦后旗| 隆回县| 鄂尔多斯市| 梁河县| 鸡东县| 治县。| 新密市| 汉寿县| 衡阳县| 浮梁县|