1. 程式人生 > >**全文檢索工具_Lucence*

**全文檢索工具_Lucence*

課程計劃:

1. 什麼是全文檢索,如何實現全文檢索
2. Lucene實現全文檢索的流程
	* 建立索引
	* 查詢索引
3. 配置開發環境
4. 入門程式
5. 分析器的分析過程
	1. 測試分析器的分析效果
	2. 第三方中文分析器
6. 索引庫維護
	1. 新增文件
	2. 刪除文件
	3. 修改文件
7. 索引庫查詢
	1. 使用Query子類查詢
	2. 使用QueryParser查詢

全文檢索概述

1. 資料分類:
	1. 結構化資料:指具有固定格式或有限長度的資料,如資料庫,元資料等。			[資料型別固定]
	2. 非結構化資料:指不定長或無固定格式的資料。如郵件,word文件等磁碟上的檔案		[資料型別不固定]
2. 結構化資料搜尋:
	1. 常見的結構化資料也就是資料庫中的資料。   使用sql語句進行查詢,很快得到結果
	2. 為什麼資料庫搜尋很容易?
		* 因為資料庫中的資料儲存是有規律的,有行有列而且資料格式、資料長度都是固定的。
		* [簡單,速度快]
3. 非結構化資料查詢方法:
	1. 順序掃描法:
		* 所謂的順序掃描,比如要找內容包含一個字串,就是一個文件一個文件的看,如果此文件包含此字串則為我們要找的檔案,藉著看下一個檔案,直到掃描所有的檔案。利用windows的搜尋也可以搜尋檔案內容,只是相當的慢。
	2. 全文檢索 [把非結構化資料變成結構化資料]:
		1. 概述:
			* 將結構化資料中的一部分資訊提取出來,重新組織,使其變得有一定結構,然後對此結構進行搜尋,從而達到搜尋相對較快的目的。
		2. 索引:
			* 這部分從非結構化資料中提取出的然後重新組織的資訊,我們稱之為索引。
		3. 分析:
			* 先根據空格進行字串拆分,得到一個單詞列表,基於單詞列表建立一個索引。然後查詢索引,根據單詞和文件的對應關係找到文件列表,這個過程就叫做全文檢索。
			* 查詢的時候,先查詢索引表,通過關鍵字與座標對應找到該關鍵字的座標,再通過座標查詢存有關鍵字的表,速度很快。
			* 樹形結構;
		4. 總結:
			* 這種先建立索引然後查詢索引的過程就叫做全文檢索。
			* 索引一次建立,多次使用,表現為每次查詢速度很快;
			* 以id為主鍵,[唯一]使用主鍵作為查詢條件速度很快。
		5. 注意:
			1. 並不是所有的表都需要建立索引,尤其是有增刪改;
			2. 只查詢的資料可以用來建立索引;
4. 如何實現全文檢索:
	* 可以使用 Lucene 實現全文檢索。Lucene 是 apache 下的一個開放原始碼的全文檢索引擎工具包。提供了完整的查詢引擎和索引引擎,部分文字分析引擎。Lucene 的目的是為軟體開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能。
5. 應用場景:
	* 對於資料量大、資料結構不固定的資料可採用全文檢索方式搜尋,比如百度、Google 等搜尋引擎、論壇站內搜尋、電商網站站內搜尋等。
	* 舉例:
		1. 搜尋引擎:     百度,360搜尋,谷歌,搜狗
		2. 站內搜尋:		 論壇搜尋,微博,文章搜尋
		3. 電商搜尋:		淘寶搜尋,京東搜尋
6. 種類:
	1. lucene
		* 它是已經被淘汰的全文檢索技術,學習它是為了學習全文檢索原理;
	2. ElasticSearch
		* 它在學成線上專案中有講解,它是最新的技術,使用率日益增加;
	3. solr
		* 它在品優購專案中有講解

lucene

1. 什麼是Lucene?
	* Lucene是一個基於java開發全文檢索工具包。
2. Lucene實現全文檢索的流程
	1. 建立索引
		1. 獲得文件
			* 原始文件:要基於那些資料來進行搜尋,那麼這些資料就是原始文件。
				* 原始文件是指要索引和搜尋的內容。原始內容包括網際網路上的網頁、資料庫中的資料、磁碟上的檔案等。
			* 搜尋引擎:使用爬蟲獲得原始文件。
				* 目的:資訊採集的目的是為了對原始內容進行索引。
			* 站內搜尋:資料庫中的資料。
				* 我們要獲取磁碟上檔案的內容,可以通過檔案流來讀取文字檔案的內容,對於pdf、doc、xls 等檔案可通過第三方提供的解析工具讀取檔案內容,比如 Apache POI 讀取 doc和 xls 的檔案內容。

			* 案例:直接使用io流讀取磁碟上的檔案,直接獲得原始文件
		2. 構建文件物件:
			1. 獲取原始內容的目的是為了索引,在索引前需要將原始內容建成文件(Document),文件中包括一個一個的域(Field),域中儲存內容。
			2. 這裡我們可以將磁碟上的一個檔案當成一個document,Document中包括一些Filed(file_name檔名稱,file_path檔案路徑,file_size檔案大小,file_content檔案內容);
			3. 域中儲存就是原始文件資料
				* 域的名稱
				* 域的值
			4. 注意:每個Document可以有多個Field,同一個Document可以有相同的Field(域名和域值都相同),每個文件都有一個唯一的編號,就是文件id;
		3. 分析文件:
			1. 就是分詞的過程
				1. 根據空格進行字串拆分,得到一個單詞列表
				2. 把單詞統一轉換為小寫
				3. 去除標點符號
				4. 去除停用詞
					* 停用詞: 無意義的詞;
					* 每個關鍵詞都封裝成一個Term物件中
						* Term中包含兩部分內容
							* 關鍵詞所在的域
							* 關鍵詞本身
						* 不同的域中拆分出來的相同的關鍵詞是不同的Term。
		4. 建立索引:
			1. 基於關鍵詞列表建立一個索引。儲存到索引庫中;
			2. 索引庫中:
				1. 索引
				2. document物件
				3. 關鍵詞和文件的對應關係
			3. 倒排索引結構:通過詞語找文件
	2. 查詢索引:
		1. 使用者查詢介面
			1. 使用者輸入查詢條件的地方
			2. 例如:百度的搜尋框
		2. 把關鍵詞封裝成一個查詢物件;
			1. 要查詢的域
			2. 要搜尋的關鍵詞
		3. 執行查詢
			1. 根據要查詢的關鍵詞到對應的域上進行搜尋。
			2. 找到關鍵詞,根據關鍵詞找到對應的文件。
		4. 渲染結果
			1. 根據文件的id找到文件物件
			2. 對關鍵詞進行高亮顯示
			3. 分頁處理
			4. 最終展示給使用者看

3. 過程:
	1. 索引過程:對搜尋的原始內容進行索引構建一個索引庫,索引過程包括:
		* 確定原始內容即要搜尋的內容->採集文件->建立文件->分析文件->索引文件
	2. 搜尋過程:從索引庫中搜索內容,搜尋過程包括:
		* 使用者通過搜尋介面->建立查詢->執行搜尋,從索引庫搜尋->渲染搜尋結果

入門程式

1. 建立索引
	* 環境:
		1. 下載
			* http://lucene.apache.org/
			* 最低要求:JDK1.8
		2. 解壓縮
		3. 檔案含義:
			1. core資料夾:  核心
			2. analysis->lucene-analyzers-common-7.4.0.jar :  分析
		4. 搭建:
			1. 建立一個java工程
			2. 新增jar:
				* lucene-analyzers-common-7.4.0.jar
				* lucene-core-7.4.0.jar
				* commons-io.jar
		5. 開始環境搭建:
			1. 建立一個java空專案
				* 建立一個Modules模組,選擇"JAVA" ;		[JDK必須在1.8以上]
		   	2. 新建一個目錄:lib
				* 新增上面的jar包
				* Dependencies->新增匯入依賴
	* 步驟:
		1. 建立一個Director物件,指定索引庫儲存的位置
		2. 基於Directory物件建立一個IndexWriter物件
		3. 讀取磁碟上的檔案,對應每個檔案建立一個文件物件
		4. 向文件物件中新增域
		5. 把文件物件寫入索引庫
		6. 關閉indexWriter物件

2. 開始
	1. 建立一個LuceneFirst類:
				 
		public class LuceneFirst {
		    @Test
		    public void createIndex() throws Exception {
		        //1、建立一個Director物件,指定索引庫儲存的位置。
		        //把索引庫儲存在記憶體中
		        //Directory directory = new RAMDirectory();
		        //把索引庫儲存在磁碟
		        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
		        //2、基於Directory物件建立一個IndexWriter物件
		        IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
		        //3、讀取磁碟上的檔案,對應每個檔案建立一個文件物件。
		        File dir = new File("C:\\A0.lucene2018\\05.參考資料\\searchsource");
		        File[] files = dir.listFiles();
		        for (File f :
		                files) {
		            //取檔名
		            String fileName = f.getName();
		            //檔案的路徑
		            String filePath = f.getPath();
		            //檔案的內容
		            String fileContent = FileUtils.readFileToString(f, "utf-8");
		            //檔案的大小
		            long fileSize = FileUtils.sizeOf(f);
		            //建立Field
		            //引數1:域的名稱,引數2:域的內容,引數3:是否儲存
		            Field fieldName = new TextField("name", fileName, Field.Store.YES);
		            //Field fieldPath = new TextField("path", filePath, Field.Store.YES);
		            Field fieldPath = new StoredField("path", filePath);
		            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
		            //Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
		            Field fieldSizeValue = new LongPoint("size", fileSize);
		            Field fieldSizeStore = new StoredField("size", fileSize);
		            //建立文件物件
		            Document document = new Document();
		            //向文件物件中新增域
		            document.add(fieldName);
		            document.add(fieldPath);
		            document.add(fieldContent);
		            //document.add(fieldSize);
		            document.add(fieldSizeValue);
		            document.add(fieldSizeStore);
		            //5、把文件物件寫入索引庫
		            indexWriter.addDocument(document);
		        }
		        //6、關閉indexwriter物件
		        indexWriter.close();
		    }


	2. 使用luke檢視索引庫中的內容
		1. 資料->luke-javafx-7.4.0-luke-reale
		2. 解壓後雙擊開啟	[最低執行版本:jdk1.9]
		3. 在name中不同類中的分詞出來的詞即便是一樣的,其型別還是不一樣。比如標題名叫apache和內容中包含apache,這裡的兩個apache不一樣;
		4. 查詢:
			1.  *:* ,它表示查詢全部;
		5. 使用此工具用於測試和檢視,實際工作中我們還是需要用程式來完成這些操作,接下來繼續我們的入門程式;
		

	3. 查詢索引庫
		1. 步驟:
			1. 建立一個Director物件,指定索引庫的位置;
			2. 建立一個IndexReader物件
			3. 建立一個IndexSearcher物件,構造方法中的引數就是indexReader物件。
			4. 建立一個Query物件,TermQuery		[它的意思就是根據關鍵詞查詢]
			5. 執行查詢,得到一個TopDocs物件
			6. 取查詢結果的總記錄數。
			7. 取文件列表
			8. 列印文件中的內容
			9. 關閉indexReader物件
		2. 實現:
			 * 繼續在LuceneFirst類中寫:	 
			 * public class LuceneFirst {
			 * ....
			 
			  @Test
			    public void searchIndex() throws Exception {
			        //1、建立一個Director物件,指定索引庫的位置
			        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
			        //2、建立一個IndexReader物件
			        IndexReader indexReader = DirectoryReader.open(directory);
			        //3、建立一個IndexSearcher物件,構造方法中的引數indexReader物件。
			        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
			        //4、建立一個Query物件,TermQuery
			        Query query = new TermQuery(new Term("name", "spring"));
			        //5、執行查詢,得到一個TopDocs物件
			        //引數1:查詢物件 引數2:查詢結果返回的最大記錄數
			        TopDocs topDocs = indexSearcher.search(query, 10);
			        //6、取查詢結果的總記錄數
			        System.out.println("查詢總記錄數:" + topDocs.totalHits);
			        //7、取文件列表
			        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
			        //8、列印文件中的內容
			        for (ScoreDoc doc :
			                scoreDocs) {
			            //取文件id
			            int docId = doc.doc;
			            //根據id取文件物件
			            Document document = indexSearcher.doc(docId);
			            System.out.println(document.get("name"));
			            System.out.println(document.get("path"));
			            System.out.println(document.get("size"));
			            //System.out.println(document.get("content"));
			            System.out.println("-----------------寂寞的分割線");
			        }
			        //9、關閉IndexReader物件
			        indexReader.close();
			    }
			
	
	4.分析器
		1. 預設使用的數標準分析器StandardAnalyzer
		2. 檢視分析器的分析效果
			1. 使用Analyzer物件的tokenStream方法返回一個TokenStream物件,詞物件中包含了最終分詞結果。
			2. 實現步驟:
				1. 建立一個Analyzer物件,StandarAnalyzer物件
				2. 使用分析器物件的tokenStream方法獲得一個TokenStream物件
				3. 向TokenStream物件中設定一個引用,相當於數一個指標;
				4. 呼叫TokenStream物件的rest方法,如果不呼叫拋異常
				5. 使用while迴圈遍歷TokenStream物件
				6. 關閉TokenStream物件
	
	
		3. 實現:
		 	 * 繼續在LuceneFirst類中寫:	 
			 * public class LuceneFirst {
			 * ....
			 * Test
			    @Test
			    public void testTokenStream() throws Exception {
			        //1)建立一個Analyzer物件,StandardAnalyzer物件
					 Analyzer analyzer = new StandardAnalyzer();
			        //2)使用分析器物件的tokenStream方法獲得一個TokenStream物件
			        TokenStream tokenStream = analyzer.tokenStream("", "2017年12月14日 - 傳智播客Lucene概述公安局Lucene是一款高效能的、可擴充套件的資訊檢索(IR)工具庫。資訊檢索是指文件搜尋、文件內資訊搜尋或者文件相關的元資料搜尋等操作。");		
			        //3)向TokenStream物件中設定一個引用,相當於數一個指標
			        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
			        //4)呼叫TokenStream物件的rest方法。如果不呼叫拋異常
			        tokenStream.reset();
			        //5)使用while迴圈遍歷TokenStream物件
			        while(tokenStream.incrementToken()) {
			            System.out.println(charTermAttribute.toString());
			        }
			        //6)關閉TokenStream物件
			        tokenStream.close();

中文分析器

1. 標準分析器的缺點:
	1. 預設分詞器是美國的一個程式設計師開發的,分詞為英文的時候,以空格為分隔點,然後拆分成各個單詞,中文只支援一個漢字一個關鍵字,準確度並不高,所以不適用;所以我們必須要使用中文分析器對其進行分析。
2. IK分詞器
	* 在詞語被分詞的時候,它被分詞成幾個部分
	* 在搜尋的時候,分詞器拿到value值,並將其也分成幾個部分
	* 然後幾個部分找幾個部分,按照關聯度高地進行排列;

3. IKAnalyze的使用方法
	1. 把IKAnalyzer的jar包新增到工程中
	2. 把配置檔案和擴充套件詞典新增到工程的classpath下;
	3. 注意:
		* 擴充套件詞典嚴禁使用windows記事本編輯,否則會使擴充套件詞典不生效;
		* 必須保證編寫的格式是utf-8    [windows記事本的utf-8不是標準的utf-8,它是utf-8+BOM,不是純的utf-8];
		* 可以使用notepad++等編輯.
	4. 擴充套件詞典[hotword.dic]: 新增一些日新月異的新詞/公司名稱等...
	5. 停用詞詞典[stopword.dic]: 無意義的詞/敏感詞等


4. 演示中文分析器的使用方法:
	1. 將IK-Analyzer...jar包匯入
	2. 將配置檔案,擴充套件詞典,停用詞典放入該包下:com.itheima.lucene
	3. 實現:
	 	 * 繼續在LuceneFirst類中寫:	 
		 * public class LuceneFirst {
		 * ....
		 * Test
		    @Test
		    public void testTokenStream() throws Exception {
		        //1)建立一個Analyzer物件,StandardAnalyzer物件
				// Analyzer analyzer = new StandardAnalyzer();		英文分析器
		        Analyzer analyzer = new IKAnalyzer();		中文分析器
		        //2)使用分析器物件的tokenStream方法獲得一個TokenStream物件
		        TokenStream tokenStream = analyzer.tokenStream("", "2017年12月14日 - 傳智播客Lucene概述公安局Lucene是一款高效能的、可擴充套件的資訊檢索(IR)工具庫。資訊檢索是指文件搜尋、文件內資訊搜尋或者文件相關的元資料搜尋等操作。");
		        //3)向TokenStream物件中設定一個引用,相當於數一個指標
		        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
		        //4)呼叫TokenStream物件的rest方法。如果不呼叫拋異常
		        tokenStream.reset();
		        //5)使用while迴圈遍歷TokenStream物件
		        while(tokenStream.incrementToken()) {
		            System.out.println(charTermAttribute.toString());
		        }
		        //6)關閉TokenStream物件
		        tokenStream.close();
5. 在程式碼中使用分析器
	1. 實現:
					 
	public class LuceneFirst {
	    @Test
	    public void createIndex() throws Exception {
	        //1、建立一個Director物件,指定索引庫儲存的位置。
	        //把索引庫儲存在記憶體中
	        //Directory directory = new RAMDirectory();
	        //把索引庫儲存在磁碟
	        Directory directory = FSDirectory.open(new File("C:\\temp\\index").toPath());
	        //2、基於Directory物件建立一個IndexWriter物件
	        IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
	        IndexWriter indexWriter = new IndexWriter(directory, config);
	        //3、讀取磁碟上的檔案,對應每個檔案建立一個文件物件。
	        File dir = new File("C:\\A0.lucene2018\\05.參考資料\\searchsource");
	        File[] files = dir.listFiles();
	        for (File f :
	                files) {
	            //取檔名
	            String fileName = f.getName();
	            //檔案的路徑
	            String filePath = f.getPath();
	            //檔案的內容
	            String fileContent = FileUtils.readFileToString(f, "utf-8");
	            //檔案的大小
	            long fileSize = FileUtils.sizeOf(f);
	            //建立Field
	            //引數1:域的名稱,引數2:域的內容,引數3:是否儲存
	            Field fieldName = new TextField("name", fileName, Field.Store.YES);
	            //Field fieldPath = new TextField("path", filePath, Field.Store.YES);
	            Field fieldPath = new StoredField("path", filePath);
	            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
	            //Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
	            Field fieldSizeValue = new LongPoint("size", fileSize);
	            Field fieldSizeStore = new StoredField("size", fileSize);
	            //建立文件物件
	            Document document = new Document();
	            //向文件物件中新增域
	            document.add(fieldName);
	            document.add(fieldPath);
	            document.add(fieldContent);
	            //document.add(fieldSize);
	            document.add(fieldSizeValue);
	            document.add(fieldSizeStore);
	            //5、把文件物件寫入索引庫
	            indexWriter.addDocument(document);
	        }
	        //6、關閉indexwriter物件
	        indexWriter.close();
	    }

索引庫維護

1. 域的型別:
	1. StringField(FieldName,FieldValue,Store.YES):
		* 這個用來構造Field,不分析,會將整個儲存在索引中,比如姓名,身份證,訂單編號等不需要分詞;		
		* 不分詞,建索引,儲存/不儲存				
		* [有些可能不需要儲存,注意:不儲存不代表不建索引庫,搜整條資料依然可以找到它]
	2. LongPoint(String name,long...Point):
		* 可以使用LongPoint/IntPoint等型別儲存資料型別的資料		
		* 分詞,建索引,不儲存
		* 如果需要儲存資料還需要使用StoreField
	3. StoreField(FieldName,FieldValue):
		* 這個Field用來構建不同型別Field
		* 不分析,不索引,但要Field要儲存在文件中
	4. TextField(FieldName,FieldValue,Store.No)或TextField(FieldName,reader)
		* 如果是一個Reader,lucene猜測內容比較多,會採用Unstored的策略;

	5. 注意:
		* 如果沒有建索引,有儲存,那麼可以查詢到該內容,但是內容中沒有該關鍵詞資料;
2. 新增文件,改造:

	Field fieldName = new TextField("name", fileName, Field.Store.YES);
   	
    Field fieldPath = new StoredField("path", filePath);
    Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
  
    Field fieldSizeValue = new LongPoint("size", fileSize);
    Field fieldSizeStore = new StoredField("size", fileSize);

	新增域:
		document.add(fieldName);
		document.add(fieldPath);
		document.add(fieldContent);
				  
		document.add(fieldSizeValue);
		document.add(fieldSizeStore);

3. 索引庫維護-新增
	1. 新建一個類:IndexManger
		* public class IndexManger{
		* 
		// 新增索引
		@Test
		public void addDocument() throws Exception {
		// 索引庫存放路徑
		Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());
		IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
		// 建立一個 indexwriter 物件
		IndexWriter indexWriter = new IndexWriter(directory, config);
		// 建立一個 Document 物件
		Document document = new Document();
		// 向 document 物件中新增域。
		// 不同的 document 可以有不同的域,同一個 document 可以有相同的域。
		document.add(new TextField("filename", " 新新增的文件", Field.Store.YES));
		document.add(new TextField("content", " 新新增的文件的內容", Field.Store.NO));
		//LongPoint 建立索引
		document.add(new LongPoint("size", 1000l));
		//StoreField 儲存資料
		document.add(new StoredField("size", 1000l));
		// 不需要建立索引的就使用 StoreField 儲存
		document.add(new StoredField("path", "d:/temp/1.txt"));
		// 新增文件到索引庫
		indexWriter.addDocument(document);
		// 關閉 indexwriter
		indexWriter.close();
		}









4. 索引庫維護-刪除	
	* 刪除文件有兩種方式:
		1. 刪除全部
		2. 根據查詢,修改
	* 示例:
		* 繼續上面的新增類...
		* @Test
		* public void deleteAllDocument() throws Exception{
		* //刪除全部文件
		* indexWriter.deleteAll();
		* //indexWriter.close();
		* }
		* @Test
		* public void deleteDocumentByQuery() throws Exception{
		* //如果刪除了索引庫,需要先建立索引庫再查詢
		* indexWriter.deleteDocuments(new Term("name","apache"))
		* indexWriter.close();
		* }
5. 索引庫維護-更新	
	* 特點:先刪除原來的,然後再進行新增操作;
	* 示例:
		* public void updateDocument() throws Exception{
		* //建立一個新的文件物件
		* Document document =new Document();
		* //向文件物件中新增域
		* document.add(new TextField("name","更新之後的文件",Field.Store.YES));
		* document.add(new TextField("name1","更新之後的文件1",Field.Store.YES));
		* document.add(new TextField("name2","更新之後的文件2",Field.Store.YES));
		* //更新索引庫
		* indexWriter.updateDocument(new Term("name","spring"),document);
		* indexWriter.close();
		* }
6. 數值範圍查詢
	1. TermQuery:	
		1. 根據關鍵詞查詢,需要指定要查詢的域及要查詢的關鍵詞;
		2. 範圍進行查詢
			
	2. 使用QueryPaser進行查詢
		1. 可以對要查詢的內容先進行分詞,然後基於分詞的結果進行查詢;
		2. 需要匯入jar包:lucene-queryparser-7.4.0.jar		

	3. 範圍查詢和QueryParser查詢的程式碼整合如下:
		
		public class SearchIndex {
		    private IndexReader indexReader;
		    private IndexSearcher indexSearcher;
		    @Before
		    public void init() throws Exception {
		        indexReader = DirectoryReader.open(FSDirectory.open(new File("C:\\temp\\index").toPath()));
		        indexSearcher = new IndexSearcher(indexReader);
		    }
		
		    @Test
		    public void testRangeQuery() throws Exception {
		        //建立一個Query物件
		        Query query = LongPoint.newRangeQuery("size", 0l, 100l);
		        printResult(query);
		    }
		
		    private void printResult(Query query) throws Exception {
		        //執行查詢
		        TopDocs topDocs = indexSearcher.search(query, 10);
		        System.out.println("總記錄數:" + topDocs.totalHits);
		        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
		        for (ScoreDoc doc:scoreDocs){
		            //取文件id
		            int docId = doc.doc;
		            //根據id取文件物件
		            Document document = indexSearcher.doc(docId);
		            System.out.println(document.get("name"));
		            System.out.println(document.get("path"));
		            System.out.println(document.get("size"));
		            //System.out.println(document.get("content"));
		            System.out.println("-----------------寂寞的分割線");
		        }
		        indexReader.close();
		    }
		
		    @Test
		    public void testQueryParser() throws Exception {
		        //建立一個QueryPaser物件,兩個引數
		        QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
		        //引數1:預設搜尋域,引數2:分析器物件
		        //使用QueryPaser物件建立一個Query物件
		        Query query = queryParser.parse("lucene是一個Java開發的全文檢索工具包");
		        //執行查詢
		        printResult(query);
		    }
		}