Lucene4.3開發之插曲之斗轉星移

    如今咱們的索引裏有2億多的數據,那麼如今的需求是,把索引裏的所有數據,讀取人後寫入txt文本里,對於這麼一個量級的數據,顯然是不可能一會兒所有讀取完的,那得要多大的內存纔可以支持下來,是一個很恐怖的內存量,因此就引入散仙今天要給你們介紹的一個功能,lucene的分頁技術。java

    在介紹分頁以前,咱們如今看看上面的那個需求,不用分頁的解決辦法,其實在lucene裏面,每個索引都會對應一個不重複的docid,而這一點跟oracle數據庫的僞列rownum同樣,偏偏正是因爲這個docid的存在,因此讓lucene在海量數據檢索是從而擁有更好的性能,咱們都知道oracle數據庫在分頁時,使用的就是僞列進行分頁,那麼咱們lucene也是同樣,既然有一個docid的存在,那麼上面的需求就很簡單了。
數據庫

    方法1:一次根據每一個docid獲取文檔而後寫入txt中,這樣以來,就避免了內存不足的缺點,可是這樣單挑讀取的話,速度上可能會變慢一點,可是能知足需求無可厚非。僞代碼以下:
oracle

try{
		directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
		IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
		IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
		for(int i=0;i<reader.numDocs();i++){//numDocs可能很大
		 Document doc=search.doc(i);//依次獲取每一個docid對應的Document
		//能夠在此部,作個批量操做,加快寫入速度
		}  
		
		 reader.close();//關閉資源
		 directory.close();//關閉鏈接
		
		}catch(Exception e){
			e.printStackTrace();
		}

lucene的分頁,總的來講有兩種形式,散仙總結以下圖標。性能

從上圖咱們能夠分析出,ScoreDocs適合在數據量不是很大的場景下進行分頁,而SearchAfter則都適合,因此,咱們要根據本身的業務需求,合理選出適合本身的分頁方式。
spa

在咱們瞭解這2種分頁技術的優缺點以後,咱們再來探討上面那個讀2億數據存入txt文本里,在這裏,ScoreDocs不適合這種場景,固然若是你內存足夠大的話,能夠嘗試下,通用分頁分批讀取的方式,能夠提高咱們寫入的效率,效果是比單挑讀取的速度是要快不少的。雖然ScoreDocs的分頁方式在本需求上不合適,可是做爲示例,下面散仙給出使用ScoreDocs進行分頁的代碼。code

try{
		directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
		IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
		IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
		
 
	     TopDocs all=search.search(new MatchAllDocsQuery(), 50000);
	     int offset=0;//起始位置
	     int pageSize=30;//分頁的條數
	     int total=30;//結束條數
	     int z=0;
	     while(z<=50){//總分頁數
	     System.out.println("==============================");
	     pageScoreDocs(offset,total,search, all.scoreDocs);//調用分頁打印
	     offset=(z*pageSize+pageSize);//下一頁的位置增量
	     z++;//分頁數+1;
	  	   total=offset+pageSize;//下一次的結束分頁量
	     }
		 reader.close();//關閉資源
		 directory.close();//關閉鏈接
		
		}catch(Exception e){
			e.printStackTrace();
		}
public void pageScoreDocs(int offset,int total,IndexSearcher searcher,ScoreDoc[] doc) throws Exception{
		//System.out.println("offset:"+offset+"===>"+total);
		for(int i=offset;i<total;i++){
			//System.out.println("i"+i+"==>"+doc.length);
		    if(i>doc.length-1){//當分頁的長度數大於總數就中止
		    	
		    	break;
		    }else{
		
		       Document dosc=searcher.doc(doc[i].doc);
			   System.out.println(dosc.get("name"));
		   
		    }
		}

最後咱們來看下使用SearcherAfter進行分頁的方式,代碼以下: (下面的代碼感受有點問題)排序

try{
		directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
		IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
		IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
	    
		 int pageStart=0;
		 ScoreDoc lastBottom=null;//至關於pageSize
		 while(pageStart<10){//這個只有是paged.scoreDocs.length的倍數加一纔有可能翻頁操做
			 TopDocs paged=null;
			 paged=search.searchAfter(lastBottom, new MatchAllDocsQuery(),null,30);//查詢首次的30條
			 if(paged.scoreDocs.length==0){
				 break;//若是下一頁的命中數爲0的狀況下,循環自動結束
			 }
			 page(search,paged);//分頁操做,此步是傳到方法裏對數據作處理的
			 
			 pageStart+=paged.scoreDocs.length;//下一次分頁總在上一次分頁的基礎上
			 lastBottom=paged.scoreDocs[paged.scoreDocs.length-1];//上一次的總量-1,成爲下一次的lastBottom
		 }
		 reader.close();//關閉資源
		 directory.close();//關閉鏈接
		
		}catch(Exception e){
			e.printStackTrace();
		}

至此,咱們已經瞭解了lucene中的分頁技術,至於,咱們在項目中該如何使用,都要根據咱們的實際狀況處理,由於分頁技術經常會跟其餘的,排序,過濾,評分等一些技術結合使用。 索引

相關文章
相關標籤/搜索