<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-6  評論-6  文章-2  trackbacks-0

    原文:http://jalorsoft.com/holen/holen_lucene_01.html

    本文是Lucene研究文集的首篇,主要介紹了Lucene的起源、發(fā)展、現(xiàn)狀,以及Luence的初步應(yīng)用,可以作為了解和學(xué)習(xí)Lucene的入門資料。

     

    1. 起源與發(fā)展

     

    Lucene是一個高性能、純Java的全文檢索引擎,而且免費、開源。Lucene幾乎適合于任何需要全文檢索的應(yīng)用,尤其是跨平臺的應(yīng)用。

     

    Lucene的作者Doug Cutting是一個資深的全文檢索專家,剛開始,Doug CuttingLucene發(fā)表在自己的主頁上,20003月將其轉(zhuǎn)移到sourceforge,于200110捐獻給Apache,作為Jakarta的一個子工程。

     

    2.使用現(xiàn)狀

     

    經(jīng)過多年的發(fā)展,Lucene在全文檢索領(lǐng)域已經(jīng)有了很多的成功案例,并積累了良好的聲譽。

     

    基于Lucene的全文檢索產(chǎn)品(Lucene本身只是一個組件,而非一個完整的應(yīng)用)和應(yīng)用Lucene的項目在世界各地已經(jīng)非常之多,比較知名的有:

    l         Eclipse:主流Java開發(fā)工具,其幫助文檔采用Lucene作為檢索引擎

    l         Jive:知名論壇系統(tǒng),其檢索功能基于Lucene

    l         Ifinder:出自德國的網(wǎng)站檢索系統(tǒng),基于Lucenehttp://ifinder.intrafind.org/

    l         MIT DSpace Federation:一個文檔管理系統(tǒng)(http://www.dspace.org/

     

    國內(nèi)外采用Lucene作為網(wǎng)站全文檢索引擎的也很多,比較知名的有:

    l         http://www.blogchina.com/weblucene/

    l         http://www.ioffer.com/

    l         http://search.soufun.com/

    l         http://www.taminn.com/

     

    (更多案例,請參見http://wiki.apache.org/jakarta-lucene/PoweredBy

     

    在所有這些案例中,開源應(yīng)用占了很大一部分,但更多的還是商化業(yè)產(chǎn)品和網(wǎng)站。毫不夸張的說,Lucene的出現(xiàn),極大的推動了全文檢索技術(shù)在各個行業(yè)或領(lǐng)域中的深層次應(yīng)用。

     

    3.初步應(yīng)用

     

    前面提到,Lucene本身只是一個組件,而非一個完整的應(yīng)用,所以若想讓Lucene跑起來,還得在Lucene基礎(chǔ)上進行必要的二次開發(fā)。

     

    下載與安裝

    首先,你需要到Lucene的官方網(wǎng)站http://jakarta.apache.org/lucene/ 去下載一份拷貝,最新版是1.4。下載后將得到一個名為lucene-1.4-final.zip的壓縮文件,將其解壓,里面有一個名為lucene-1.4-final.jar的文件,這就是Lucene組件包了,若需要在項目使用Lucene,只需要把lucene-1.4-final.jar置于類路徑下即可,至于解壓后的其他文件都是參考用的。

     

    接下來,我用Eclipse建立一個工程,實現(xiàn)基于Lucene的建庫、記錄加載和記錄查詢等功能。

     

     

    如上圖所示,這是開發(fā)完成后的工程,其中有三個源文件CreateDataBase.javaInsertRecords.javaQueryRecords.java,分別實現(xiàn)建庫、入庫、檢索的功能。

     

    以下是對這三個源文件的分析。

     

    建庫源碼及說明

     

    CreateDataBase.java

    package com.holen.part1;

     

    import java.io.File;

    import org.apache.lucene.analysis.standard.StandardAnalyzer;

    import org.apache.lucene.index.IndexWriter;

     

    /**

     * @author Holen Chen

     * 初始化檢索庫

     */

    public class CreateDataBase {

     

        public CreateDataBase() {  

        }

       

        public int createDataBase(File file){

           int returnValue = 0;

           if(!file.isDirectory()){

               file.mkdirs();

           }

           try{

               IndexWriter indexWriter = new IndexWriter(file,new StandardAnalyzer(),true);

               indexWriter.close();

               returnValue = 1;

           }catch(Exception ex){

               ex.printStackTrace();

           }

           return returnValue;

        }

       

        /**

         * 傳入檢索庫路徑,初始化庫

         * @param file

         * @return

         */

        public int createDataBase(String file){

           return this.createDataBase(new File(file));  

        }

     

        public static void main(String[] args) {

           CreateDataBase temp = new CreateDataBase();

           if(temp.createDataBase("e:\\lucene\\holendb") == 1){

               System.out.println("db init succ");

           }

        }

    }

     

     

    說明:這里最關(guān)鍵的語句是IndexWriter indexWriter = new IndexWriter(file,new StandardAnalyzer(),true)

     

    第一個參數(shù)是庫的路徑,也就是說你準(zhǔn)備把全文檢索庫保存在哪個位置,比如main方法中設(shè)定的“e:\\lucene\\holendb”,Lucene支持多庫,且每個庫的位置允許不同。

     

    第二個參數(shù)是分析器,這里采用的是Lucene自帶的標(biāo)準(zhǔn)分析器,分析器用于對整篇文章進行分詞解析,這里的標(biāo)準(zhǔn)分析器實現(xiàn)對英文(或拉丁文,凡是由字母組成,由空格分開的文字均可)的分詞,分析器將把整篇英文按空格切成一個個的單詞(在全文檢索里這叫切詞,切詞是全文檢索的核心技術(shù)之一,Lucene默認只能切英文或其他拉丁文,默認不支持中日韓等雙字節(jié)文字,關(guān)于中文切詞技術(shù)將在后續(xù)章節(jié)重點探討)。

     

    第三個參數(shù)是是否初始化庫,這里我設(shè)的是truetrue意味著新建庫或覆蓋已經(jīng)存在的庫,false意味著追加到已經(jīng)存在的庫。這里新建庫,所以肯定需要初始化,初始化后,庫目錄下只存在一個名為segments的文件,大小為1k。但是當(dāng)庫中存在記錄時執(zhí)行初始化,庫中內(nèi)容將全部丟失,庫回復(fù)到初始狀態(tài),即相當(dāng)于新建了該庫,所以真正做項目時,該方法一定要慎用。

     

    加載記錄源碼及說明

     

    InsertRecords.java

    package com.holen.part1;

     

    import java.io.File;

    import java.io.FileReader;

    import java.io.Reader;

    import org.apache.lucene.analysis.standard.StandardAnalyzer;

    import org.apache.lucene.document.Document;

    import org.apache.lucene.document.Field;

    import org.apache.lucene.index.IndexWriter;

     

    /**

     * @author Holen Chen

     * 記錄加載

     */

    public class InsertRecords {

     

        public InsertRecords() {

        }

       

        public int insertRecords(String dbpath,File file){

           int returnValue = 0;

           try{

               IndexWriter indexWriter

                = new IndexWriter(dbpath,new StandardAnalyzer(),false);

               this.addFiles(indexWriter,file);

               returnValue = 1;

           }catch(Exception ex){

               ex.printStackTrace();

           }

           return returnValue;

        }

       

        /**

         * 傳入需加載的文件名

         * @param file

         * @return

         */

        public int insertRecords(String dbpath,String file){

           return this.insertRecords(dbpath,new File(file));

        }

       

        public void addFiles(IndexWriter indexWriter,File file){

           Document doc = new Document();

           try{

               doc.add(Field.Keyword("filename",file.getName()));  

                     

               //以下兩句只能取一句,前者是索引不存儲,后者是索引且存儲

               //doc.add(Field.Text("content",new FileReader(file))); 

               doc.add(Field.Text("content",this.chgFileToString(file)));

              

               indexWriter.addDocument(doc);

               indexWriter.close();

           }catch(Exception ex){

               ex.printStackTrace();

           }

        }

       

        /**

         * 從文本文件中讀取內(nèi)容

         * @param file

         * @return

         */

        public String chgFileToString(File file){

           String returnValue = null;

           StringBuffer sb = new StringBuffer();

           char[] c = new char[4096];

           try{

               Reader reader = new FileReader(file);

               int n = 0;

               while(true){            

                  n = reader.read(c);

                  if(n > 0){

                      sb.append(c,0,n);

                  }else{

                      break;

                  }

               }

               reader.close();

           }catch(Exception ex){

               ex.printStackTrace();

           }

           returnValue = sb.toString();

           return returnValue; 

        }

     

        public static void main(String[] args) {

           InsertRecords temp = new InsertRecords();

           String dbpath = "e:\\lucene\\holendb";

           //holen1.txt中包含關(guān)鍵字"holen""java"

           if(temp.insertRecords(dbpath,"e:\\lucene\\holen1.txt") == 1){

               System.out.println("add file1 succ");

           }

           //holen2.txt中包含關(guān)鍵字"holen""chen"

           if(temp.insertRecords(dbpath,"e:\\lucene\\holen2.txt") == 1){

               System.out.println("add file2 succ");

           }  

        }

    }

     

     

    說明:這個類里面主要有3個方法insertRecords(String dbpath,File file)addFiles(IndexWriter indexWriter,File file)chgFileToString(File file)

     

    ChgFileToString方法用于讀取文本型文件到一個String變量中。

     

    InsertRecords方法用于加載一條記錄,這里是將單個文件入全文檢索庫,第一個參數(shù)是庫路徑,第二個參數(shù)是需要入庫的文件。

     

    InsertRecords需要調(diào)用addFilesaddFiles是文件入庫的真正執(zhí)行者。AddFiles里有如下幾行重點代碼:

    doc.add(Field.Keyword("filename",file.getName()));

    注意,在Lucene里沒有嚴(yán)格意義上表,Lucene的表是通過Field類的方法動態(tài)構(gòu)建的,比如Field.Keyword("filename",file.getName())就相當(dāng)于在一條記錄加了一個字段,字段名為filename,該字段的內(nèi)容為file.getName()

     

     

    常用的Field方法如下:

    方法

    切詞

    索引

    存儲

    用途

    Field.Text(String name, String value)

    Y

    Y

    Y

    標(biāo)題,文章內(nèi)容

    Field.Text(String name, Reader value)

    Y

    Y

    N

    META信息

    Field.Keyword(String name, String value)

    N

    Y

    Y

    作者

    Field.UnIndexed(String name, String value)

    N

    N

    Y

    文件路徑

    Field.UnStored(String name, String value)

    Y

    Y

    N

    與第二種類似

     

    為了更深入的了解全文檢索庫,我們可以將全文檢索庫與通常的關(guān)系型數(shù)據(jù)庫(如OracleMysql)作一下對比。

     

    全文檢索庫對關(guān)系型數(shù)據(jù)庫對比

    對比項

    全文檢索庫(Lucene

    關(guān)系型數(shù)據(jù)庫(Oracle

    核心功能

    以文本檢索為主,插入(insert)、刪除(delete)、修改(update)比較麻煩,適合于大文本塊的查詢。

    插入(insert)、刪除(delete)、修改(update)十分方便,有專門的SQL命令,但對于大文本塊(如CLOB)類型的檢索效率低下。

    Oracle類似,都可以建多個庫,且各個庫的存儲位置可以不同。

    可以建多個庫,每個庫一般都有控制文件和數(shù)據(jù)文件等,比較復(fù)雜。

    沒有嚴(yán)格的表的概念,比如Lucene的表只是由入庫時的定義字段松散組成。

    有嚴(yán)格的表結(jié)構(gòu),有主鍵,有字段類型等。

    記錄

    由于沒有嚴(yán)格表的概念,所以記錄體現(xiàn)為一個對象,在Lucene里記錄對應(yīng)的類是Document

    Record,與表結(jié)構(gòu)對應(yīng)。

    字段

    字段類型只有文本和日期兩種,字段一般不支持運算,更無函數(shù)功能。

    Lucene里字段的類是Field,如documentfield1,field2…

    字段類型豐富,功能強大。

    recordfield1,field2…

    查詢結(jié)果集

    Lucene里表示查詢結(jié)果集的類是Hits,如hitsdoc1,doc2,doc3…

    JDBC為例, Resultsetrecord1,record2,record3...

     

    兩種庫對比圖如下:

    Lucene

    doc(field1,field2..),doc(field1,field2..)

    入庫:  indexer

    Hits(doc(field1,field2..),doc(field1,field2..)...)

    查詢:  seracher

    Oracle

    record(field1,field2..),doc(field1,field2..)

    入庫:  insert

    rResultset(record(field1,field2..),doc(field1,field2..)

     

    查詢:  select

     

     

     

     

     

     

     

     

     

     

     

     


    檢索源碼及說明

     

    QueryRecords.java

    package com.holen.part1;

     

    import java.util.ArrayList;

    import org.apache.lucene.analysis.standard.StandardAnalyzer;

    import org.apache.lucene.document.Document;

    import org.apache.lucene.queryParser.QueryParser;

    import org.apache.lucene.search.Hits;

    import org.apache.lucene.search.IndexSearcher;

    import org.apache.lucene.search.Query;

    import org.apache.lucene.search.Searcher;

     

    /**

     * @author Holen Chen

     * 檢索查詢

     */

    public class QueryRecords {

     

        public QueryRecords() {

        }

       

        /**

         * 檢索查詢,將結(jié)果集返回

         * @param searchkey

         * @param dbpath

         * @param searchfield

         * @return

         */

        public ArrayList queryRecords(String searchkey,String dbpath,String searchfield){

           ArrayList list = null;

           try{

               Searcher searcher = new IndexSearcher(dbpath);

               Query query

                = QueryParser.parse(searchkey,searchfield,new StandardAnalyzer());

               Hits hits = searcher.search(query);

               if(hits != null){

                  list = new ArrayList();

                  int temp_hitslength = hits.length();

                  Document doc = null;

                  for(int i = 0;i < temp_hitslength; i++){

                      doc = hits.doc(i);

                      list.add(doc.get("filename"));

                  }

               }

           }catch(Exception ex){

               ex.printStackTrace();

           }

           return list;

        }

     

        public static void main(String[] args) {

           QueryRecords temp = new QueryRecords();      

           ArrayList list = null;

           list = temp.queryRecords("holen","e:\\lucene\\holendb","content");

           for(int i=0;i< list.size();i++){

               System.out.println((String)list.get(i));

           }      

        }

    }

     

     

    說明:該類中Searcher負責(zé)查詢,并把查詢結(jié)果以Hits對象集方式返回,Hits好比JDBC中的RecordSetHitsDocument的集合,每個Document相當(dāng)于一條記錄,Document中包含一個或多個字段,可以通過Document.get(“字段名”)方法得到每個字段的內(nèi)容。

     

    通過這三個類,就完成了一個簡單的基于Lucene的全文檢索應(yīng)用。

     

    4.總結(jié)

     

    Lucene十分精練純粹,就一個jar包,引入到你的工程中,調(diào)用其接口,就可以為你的應(yīng)用增添全文檢索功能。

     

    通過上一節(jié)的初步應(yīng)用會發(fā)現(xiàn),Lucene使用起來很簡單,與JDBC有些類似,應(yīng)用時重點掌握好IndexWriterDocumentFieldSearcher等幾個類即可。

     

    Lucene的結(jié)構(gòu)很清晰,每個package司職一項,比如org.apache.Lucene.search負責(zé)檢索,org.apache.Lucene.index索引,org.apache.Lucene.analysis切詞等,且Lucene的主要動作都采用了抽象類,擴展起來十分方便。

     

    相對于一些商業(yè)化全文檢索,Lucene的入庫速度更快。因為它的存儲采取分步合并的方法,先建立小索引,待時機成熟才把小索引合并到大索引樹上。因此,我們在操作應(yīng)用數(shù)據(jù)時可以同步進行全文檢索庫的操作而不會(或許很少)影響系統(tǒng)的效能。

     

    Lucene性能穩(wěn)定,使用簡單,而且開源免費,有Apache基金在后面做支撐,資金和技術(shù)力量都十分雄厚,這兩年也一直是穩(wěn)步更新,每次新版本的推出,業(yè)界均爭相報導(dǎo)。

     

    參考資料

     

    1.  Introduction to Text Indexing with Apache Jakarta LuceneOtis Gospodnetic

    2.  Lucene Introduction in Chinese(車東)

    3.  Lucene TutorialSteven J. Owens

     

    作者簡介

     

    陳光 J2EE項目經(jīng)理,熟悉EJBXML,致力于Aapche Jakarta項目的應(yīng)用與推廣,可通過holen@263.net與作者聯(lián)系。

    posted on 2005-06-28 16:01 gaich 閱讀(314) 評論(0)  編輯  收藏 所屬分類: J2EE應(yīng)用

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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲Aⅴ无码一区二区二三区软件 亚洲AⅤ视频一区二区三区 | 亚洲人成网亚洲欧洲无码久久| 亚洲性日韩精品一区二区三区| 亚洲AV第一页国产精品| 亚洲免费视频网址| 春暖花开亚洲性无区一区二区| 免费中文字幕视频| 在线观看免费中文视频| 日本免费中文字幕在线看| 中文字幕亚洲第一| 亚洲中文字幕AV在天堂| 成全视成人免费观看在线看| 日本h在线精品免费观看| 亚洲国产a级视频| 亚洲视频一区二区三区| 四虎精品免费永久免费视频| 久久精品免费一区二区| 波多野结衣亚洲一级| 永久黄网站色视频免费直播 | 亚洲成人在线网站| 91精品成人免费国产片| 亚洲色偷偷综合亚洲av78| 国产精品免费AV片在线观看| 永久免费毛片手机版在线看| 无人视频免费观看免费视频 | 免费人成在线观看视频播放| 亚洲国产日产无码精品| 成年女人毛片免费观看97| 亚洲人成网www| 岛国精品一区免费视频在线观看| 亚洲精品卡2卡3卡4卡5卡区| 亚洲AV香蕉一区区二区三区| 免费人成视频在线观看网站| 国产国拍亚洲精品mv在线观看| 成人在线免费视频| 亚洲人成网址在线观看| 女人张腿给男人桶视频免费版| 激情五月亚洲色图| 免费大香伊蕉在人线国产 | 二级毛片免费观看全程| 亚洲网站在线播放|