2013-03-23 8 views
5

私はLucene 4.2を使用しており、結果ページングを実装しています。Lucene 4 Pagination

IndexSearcher.searchAfterは「次のページ」機能を効率的に実装する方法を提供しますが、「前のページ」や「ページを表示」機能の実装にはどのような方法が最適ですか?たとえば、IndexSearcher.searchBeforeはありません。

ページサイズを指定して合計ページ数を決定し、ScoreDoc[]アレイが各ページの "後" ScoreDocを追跡することを検討していました(結果がページングされるときに配列にデータが読み込まれます)。これにより、IndexSearcher.searchAfter(最悪の場合はnull)での使用に「最も近い」ScoreDocを使用することができます。

これは意味がありますか?より良いアプローチがありますか?

+0

こんにちは、同じ問題に直面しているlucene 4.xとページングのページングについて説明できますか。 –

+0

私は上記第3段落で説明したアプローチを使用しています。非常に深いページング(驚きなし)を除いて、かなり良いパフォーマンスを発揮します。 – hudsonb

答えて

11

私はLucene 4.8を使用しており、ページ分割を含むRESTインターフェイスに取り組んでいます。 私の解決策は、TopScoreDocCollectorを使用し、topDocs(int startIndex、int numberOfhits)メソッドを呼び出すことでした。開始インデックスは、ゼロベースのページ番号にヒット数を掛けて計算されます。

... 
DirectoryReader reader = DirectoryReader.open(MMapDirectory.open(java.io.File(indexFile)); 
IndexSearcher searcher = new IndexSearcher(reader); 
TopScoreDocCollector collector = TopScoreDocCollector.create(MAX_RESULTS, true); // MAX_RESULTS is just an int limiting the total number of hits 
int startIndex = (page -1) * hitsPerPage; // our page is 1 based - so we need to convert to zero based 
Query query = new QueryParser(Version.LUCENE_48, "All", analyzer).parse(searchQuery); 
searcher.search(query, collector); 
TopDocs hits = collector.topDocs(startIndex, hitsPerPage); 
... 

私のRESTインターフェイスは、ページ番号と1ページあたりのヒット数をパラメータとして受け付けます。 ページの適切な値を指定して新しいリクエストを送信するのと同じくらい簡単です。

+0

ありがとうJaimie、私はこのアプローチが好きです。 – hudsonb

4

私はJaimieによって説明された解決策に同意します。しかし、私は、あなたが認識しなければならないことと、検索エンジンの一般的な仕組みを理解する助けとなる別の側面を指摘したいと思います。

TopDocCollectorを使用すると、結果がスコアやその他のソート基準でソートされる前に、検索クエリと一致するヒットの量を定義できます。

は、次の例を参照してください:

collector = TopScoreDocCollector.create(9999, true); 
searcher.search(parser.parse("Clone Warrior"), collector); 
// get first page 
topDocs = collector.topDocs(0, 10); 
int resultSize=topDocs.scoreDocs.length; // 10 or less 
int totalHits=topDocs.totalHits; // 9999 or less 

私たちは、検索フレーズ「クローン戦士」を含む9999個のドキュメントの最大値を収集するために、ここでのLuceneを教えてください。つまり、この検索句を含む9999件を超えるドキュメントがインデックスに含まれている場合、コレクタは9999ヒットで埋められた後に停止します。

これは、検索結果がより良くなるほどMAX_RESULTSを選択するほど大きくなることを意味します。しかし、これはヒット数が多いと予想される場合にのみ関係します。 "luke skywalker"を検索した場合、ヒット数が1になるだけでなく、ヒット数が1になることもあります。

MAX_RESULTSを変更すると、ソートが実行される収集されたヒットに人間のユーザが特定の文書を見逃すことができないように、MAX_RESULTSを十分大きなサイズに設定するのが事実です。この概念は、完全なデータプールを常に考慮するSQLデータベースの動作に全く反対します。

しかし、ルーゼンはまた別のメカニズムをサポートしています。コレクタのMAX_RESULTSを定義する代わりに、結果セットを待つ時間を定義することもできます。たとえば、300ms後に常にコレクタを停止したいと定義することができます。これは、パフォーマンス問題のためにアプリケーションを保護するための良いアプローチです。しかし、MAX_RESULTSのパラメータを設定するか、または最大待機時間を無限の値に設定するよりも、関係するすべてのドキュメントを確実にカウントしたい場合は、