본문 바로가기

Lucene

[about Lucene] NRTManager (Lucene 3.6.1)

NearRealTime Manager입니다.


앞서 포스팅하였던 SearcherManager를 사용할때 생성자에 IndexWriter를 주면

IndexWriter로부터 NRT IndexReader (루씬사용자들이 아마.. IndexWriter로부터 얻어내는 IndexReader를 NRT IndexReader라고 하는 듯 합니다.)를 얻어내서, IndexWriter를 통한 Document add/update/delete등의 반영이후 commit이 없어도

mayRefresh() / acquire() 메서드를 통해 얻은 IndexSearcher가 변경된 내용을 가져 올 수 있는 예제를 봤습니다.


NRTManager 역시 Near Real Time Search를 위한 유틸성 클래스입니다.


다만 SearcherManager보다 좀 더 구체적인 API가 제공됩니다.


일단, NRTManager는 아래와 같이 생성합니다. 




생성자로 넘겨주는 IndexWriter가 그냥 IndexWriter가 아니라 NRTManager.TrackingIndexWriter인 것이 특징입니다.

기본적으로 IndexWriter가 가지고 있는 add/update/delete 등의 메서드를 가지고 있고, commit/close는 가지고 있지 않습니다. 이 TrackingIndexWriter의 특징은 위의 add/update/delete 메서드를 통해 인덱스에 변경이 일어날 경우 Generation Token 값을 넘겨준다는 것 입니다.


예를들어서 위의 처음 NRTManager를 생성한 경우에는 generation이 0이고, TrackingIndexWriter를 통해서 Document를 하나 add 할 때 return되는 generation의 값은 1입니다. 이 generation이 NRTManager하고도 연결이 되는데요.. 즉, generation이 0인 IndexSearcher는 새로 add된 Document를 반영하지 못 하고, 1인 IndexSearcher는 이를 반영 할 수 있게 됩니다.


물론 NRTManager에서는 이 generation의 값으로 해당 generation에 속하는 IndexSearcher를 얻을 수는 없지만, 이를 위한

클래스가 또 따로 준비가 되어있습니다. (SearchLifeTimeManager) 이는 나중에 따로 또 포스팅 할 예정입니다.


아래의 테스트 코드를 보겠습니다.



처음 nrtManager로부터 가져온 generation은 0이고, Document를 add하고 maybeRefresh를 실행 한 다음의 generation 값은 1입니다. 잘 보셔야 할 부분은, trackingIndexWriter.addDocument를 실행하면서 return된 newGeneration의 값이 1이라는 점입니다. 이를 통해서 maybeRefresh를 실행 한 이후의 Generation 값을 예측 할 수 있습니다.

참고로, addDocument를 연속으로 두번한다고해서 newGeneration의 값이 계속 올라가는 것은 아닙니다. 어디까지나 currentGeneration를 기준으로 생성됩니다.


또한, nrtManager에는 waitForGeneration이라는 메서드가 있습니다.

아래의 테스트 코드를 보겠습니다.



일단, watiForGeneration 메서드 자체는 지정된 generation이 currentGeneration이 될 때까지 기다립니다.

위 첫번째 테스트 코드의 경우 , nrtManager.waitForGeneration(1); 은 아무런 역할을 하지 않습니다. maybeRefresh() 메서드가 먼저 실행되면서 currentGeneration이 1이 된 상태이기 때문입니다. 만약, nrtManager.waitForGeneration(2); 였다면

다른 어딘가에서 maybeRefresh()를 실행하여 currentGeneration을 증가시키 않는이상 계속 blocking상태로 있게 됩니다.


nrtManager.waitForGeneration(3); 이면 어떻게 될까요?


Exception이 발생합니다.


그리고, WaitListener를 구현하면, waitForGeneration실행시의 추가 동작을 정의 할 수도 있습니다.


이제, 실제 Near Real Time Search의 예제 코드를 보겠습니다.



코드를 보시면 indexSearcher가 각각 다른 결과를 보여주는 것을 보실 수 있습니다.


아래의 블로그에서는 NRTManager에서 이 generation 값을 가지고 SearcherManager를 얻어서 해당 generation의 IndexSearcher를 얻어 올 수 있다고 되어있는듯 한데.. 3.6.0으로 넘어오면서 그 기능이 사라지고 대신, SearchLifetimeManager가 새로 생긴 듯 합니다. 


그래서인지... 이 NRTManager만 가지고는 generation token으로 할 수 있는 것이 좀 애매합니다. 3.6에서는 해당 generation의 Searcher나 SearcherManager를 가져 올 수가 없어서....


왠지 4.0에서는 또 완전히 다 바뀌어 있을 것 같은데.... 좀 봐야겠네요...


참고블로그 : http://blog.mikemccandless.com/2011/11/near-real-time-readers-with-lucenes.html

테스트코드 : https://github.com/need4spd/aboutLucene