Lucene是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎.它提供了一個簡單卻強大的應用程式接口,能夠做全文索引和搜尋。在Java開發環境里Lucene是一個成熟的免費開源工具。就其本身而言,Lucene是很受歡迎的免費Java資訊檢索程式庫。因公司需要,所以開始爬資料學習,希望得到更多大神的指點.然后把這塊做好!
當前版本為4.2, 官方網站: http://lucene.apache.org/
在全文索引工具中,都是由3部分組成
1.索引部分
2.分詞部分
3.搜索部分
建立索引的步驟
1.創建Directory
2.創建IndexWriter
3.創建Document對象
4.為Document添加Field
/** * Description: 建立索引 * */ public void createIndex(){ IndexWriter indexWriter = null; try { //1.創建Directory Directory directory = new RAMDirectory(); //在內存中建立索引 //2.創建IndexWriter IndexWriterConfig indexWiterConfig = new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36)); indexWriter = new IndexWriter(directory, indexWiterConfig); //3.創建Document對象 Document document = new Document(); //4.為Document添加Field File filePath = new File("luence/example"); for(File file: filePath.listFiles()){ //為該文件夾下的所有文件建立索引 document = new Document(); //傳入文件內容 document.add(new Field("content",new FileReader(file))); //傳入文件名 document.add(new Field("filename", file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED)); //傳入文件路徑 document.add(new Field("path",file.getAbsolutePath(),Field.Store.YES,Field.Index.NOT_ANALYZED)); //5.通過IndexWriter添加文檔到索引中 indexWriter.addDocument(document); } } catch (Exception e) { e.printStackTrace(); }finally{ if(indexWriter!=null){ try { indexWriter.close(); } catch (Exception e) { e.printStackTrace(); } } } }
上面實例中在內存中創建索引.也可以在硬盤上創建索引:
Directory directory2 = FSDirectory.open(new File("F:/luence/index")); //在硬盤上的F:/luence/index下建立索引
搜索操作的步驟:
1.創建Directory
2.創建IndexReader
3.根據IndexReader創建IndexSearcher
4.創建搜索的Query
5.根據Searcher搜索並且返回TopDocs
6.根據TopDocs獲取ScoreDoc對象
7.根據Seacher和ScoreDoc對象獲取具體的Document對象
8.根據Document對象獲取需要的值
9.關閉IndexReader
public void searcher(){ try { //1.創建Directory 在硬盤上的F:/luence/index下建立索引 Directory directory = FSDirectory.open(new File("F:/luence/index")); //2.創建IndexReader IndexReader indexReader = IndexReader.open(directory); //3.根據IndexReader創建IndexSearcher IndexSearcher indexSearcher = new IndexSearcher(indexReader); //4.創建搜索的Query //創建parser來確定要搜索文件的內容,第二個參數表示搜索的域, 實例中為"content",表示在內容中查找 QueryParser queryParser = new QueryParser(Version.LUCENE_36,"content",new StandardAnalyzer(Version.LUCENE_36)); //創建query,表示搜索域為content中包含Java關鍵字的文檔 Query query = queryParser.parse("Java"); //搜索包含關鍵字Java的信息 //5.根據Searcher搜索並且返回TopDocs //查詢,第二個參數表示顯示前10條記錄 TopDocs topDoc = indexSearcher.search(query, 10); //6.根據TopDocs獲取ScoreDoc對象 ScoreDoc[] scoreDocs = topDoc.scoreDocs; for(ScoreDoc scoreDoc : scoreDocs){ //7.根據Seacher和ScoreDoc對象獲取具體的Document對象 Document document = indexSearcher.doc(scoreDoc.doc); //8.根據Document對象獲取需要的值 System.out.println(document.get("filename") + "[" + document.get("path") + "]"); } //9.關閉IndexReader indexReader.close(); } catch (Exception e) { // TODO: handle exception } }
文檔Document和域Field的關系
文檔Document相當於關系表中的每一條記錄,域相當於表中的每一個字段,先創建文檔,之后為文檔添加域.
域存儲選項和域索引選項,均需要在域添加的時候設置
存儲域選項
Field.Store.YES表示把這個域中的內容完全存儲到文件中,方便進行文本的還原
Field.Store.NO表示把這個域中的內容不存儲到文件中,但是可以被索引,此時內容無法還原(即無法document.get());
索引域選項
Field.Index.ANALYZED:進行分詞和索引,適用於標題和內容等
Field.Index.NOT_ANALYZED:進行索引,但是不進行分詞,像身份證號,姓名,ID等,適用於精確索索
Field.Index.ANALYZED_NO_NORMS:進行分詞但是不存儲norms信息,這個norms中包括了創建索引的時間和權值等信息
Field.Index.NOT_ANALYZED_NO_NORMS:即不進行分詞也不存儲norms信息
Field.Index.NO:不進行索引
最佳實踐
Field.Index.NOT_ANALYZED_NO_NORMS, Field.Store.YES標識符(主鍵,文件名),電話號碼,身份證號,姓名,日期
Field.Index.ANALYZED, Field.Store.YES文檔標題和摘要
Field.Index.ANALYZED, Field.Store.NO文檔正文
Field.Index.NO,Field.Store.YES文檔類型,數據庫主鍵(不進行索引)
Field.Index.NOT_ANALYZED,Field.Store.NO 隱藏關鍵字
刪除文檔操作
public void delete(){ IndexWriter indexWriter = null; try { IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36)); indexWriter = new IndexWriter(directory, indexWriterConfig); //參數是一個選項,可以是一個Query,也可以是一個Term,Term是一個精確查找的值 //此時刪除的文檔並不會完全被刪除,而是存儲在一個回收站中,可以恢復 //使用Reader可以有效的恢復取到的文檔數 indexWriter.deleteDocuments(new Term("id","1")); } catch (Exception e) { e.printStackTrace(); }finally{ if(indexWriter!=null){ try { indexWriter.close(); } catch (Exception e) { e.printStackTrace(); } } } }
indexWriter.deleteDocuments()文檔並不會完全被刪除,而是存儲在一個回收站中,我們可以編寫查詢類來進行查詢
public void query(){ try { IndexReader indexReader = IndexReader.open(directory); System.out.println("存儲的文檔數:" + indexReader.numDocs()); System.out.println("總存儲量:" + indexReader.maxDoc()); System.out.println("被刪除的文檔:" + indexReader.numDeletedDocs()); } catch (Exception e) { e.printStackTrace(); } }
測試程序
LuenceIndex luence = new LuenceIndex("F:/luence/index"); luence.index(); System.out.println("===== 首次建立索引后進行查詢 ====="); luence.query(); luence.delete(); System.out.println("===== 調用刪除操作后進行查詢 ====="); luence.query();
分析程序運行結果
===== 首次建立索引后進行查詢 ===== 存儲的文檔數:5 總存儲量:5 被刪除的文檔:0 ===== 調用刪除操作后進行查詢 ===== 存儲的文檔數:4 總存儲量:5 被刪除的文檔:1
使用IndexReader可以有效的恢復刪除到回收站的文檔
public void recovery(){ try { IndexReader indexReader = IndexReader.open(directory,false); //通過IndexReader進行恢復,恢復時,必須把IndexReader的只讀(readOnly)設置為false indexReader.undeleteAll(); indexReader.close(); } catch (Exception e) { e.printStackTrace(); } }
如果要清空回收站中的內容,需要使用IndexWriter中的forceMergeDeletes()方法
public void forceDelete(){ IndexWriter indexWriter = null; try { IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36)); indexWriter = new IndexWriter(directory, indexWriterConfig); indexWriter.forceMergeDeletes(); } catch (Exception e) { e.printStackTrace(); }finally{ if(indexWriter!=null){ try { indexWriter.close(); } catch (Exception e2) { e2.printStackTrace(); } } } }
這次測試
public static void main(String[] args) { LuenceIndex luence = new LuenceIndex("F:/luence/index"); luence.index(); System.out.println("===== 首次建立索引后進行查詢 ====="); luence.query(); luence.delete(); System.out.println("===== 調用刪除操作后進行查詢 ====="); luence.query(); luence.forceDelete(); System.out.println("===== 清空回收站內容后進行查詢 ====="); luence.query(); }
運行結果
===== 首次建立索引后進行查詢 ===== 存儲的文檔數:5 總存儲量:5 被刪除的文檔:0 ===== 調用刪除操作后進行查詢 ===== 存儲的文檔數:4 總存儲量:5 被刪除的文檔:1 ===== 清空回收站內容后進行查詢 ===== 存儲的文檔數:4 總存儲量:4 被刪除的文檔:0
Luence更新操作
public void update(){ IndexWriter indexWriter = null; try { IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36,new StandardAnalyzer(Version.LUCENE_36)); indexWriter = new IndexWriter(directory, indexWriterConfig); //Luence並沒有提供更新,這里的更新操作其實是先刪除再添加的操作合集 Document document = new Document(); document.add(new Field("id","updateId",Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS)); document.add(new Field("email","updateEmail",Field.Store.YES,Field.Index.NOT_ANALYZED)); document.add(new Field("content","updateContent",Field.Store.NO,Field.Index.ANALYZED)); document.add(new Field("name","updateName",Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS)); //更新Id為2的數據 indexWriter.updateDocument(new Term("id","2"), document); } catch (Exception e) { e.printStackTrace(); }finally{ if(indexWriter!=null){ try { indexWriter.close(); } catch (Exception e) { e.printStackTrace(); } } } }
轉載請注明出處:[http://www.cnblogs.com/dennisit/archive/2013/04/06/3002863.html]