咱們先來看下下面的問題,如今咱們的索引裏有2億多的數據,那麼如今的需求是,把索引裏的所有數據,讀取而後寫入txt文本里,對於這麼一個量級的數據,顯然是不可能一會兒所有讀取完的,那得要多大的內存纔可以支持下來,是一個很恐怖的內存量,因此就引入散仙今天要給你們介紹的一個功能,Lucene的分頁技術。
在介紹分頁以前,咱們先來看看上面的那個需求,不用分頁的解決辦法,
其實在lucene裏面,每個索引都會對應一個不重複的docid,而這一點跟Oralce數據庫的僞列rownum同樣,偏偏正是因爲這個docid的存在,因此讓lucene在海量數據檢索時從而擁有更好的性能,咱們都知道Oracle數據庫在分頁時,使用的就是僞列進行分頁,那麼個人lucene也是同樣,既然有一個docid的存在,那麼上面的需求就很簡單了。
方法一:依次根據每一個docid獲取文檔而後寫入txt中,這樣的以來,就避免了內存不足的缺點,可是這樣單條讀取的話,速度上可能會慢一點,但能知足需求無可厚非。僞代碼以下
java
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的分頁,總的來講有兩種形式,總結以下圖表格。(若是存在不合適之處,歡迎指正!)
數據庫
編號 | 方式 | 優勢 | 缺點 |
1 | 在ScoresDocs裏進行分頁 | 無需再次查詢索引,速度很快 | 在海量數據時,會內存溢出 |
2 | 利用SearchAfter,再次查詢分頁 | 適合大批量數據的分頁 | 再次查詢,速度相對慢一點,但能夠利用緩存彌補 |
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中的分頁技術,至於,咱們在項目中該如何使用,都要根據咱們的實際狀況處理,由於分頁技術經常會跟其餘的,排序,過濾,評分等一些技術結合使用。
性能