2013-03-23 9 views
5

Tôi đang sử dụng Lucene 4.2 và đang thực hiện phân trang kết quả.Lucene 4 Pagination

IndexSearcher.searchAfter cung cấp cách hiệu quả để triển khai chức năng "trang tiếp theo" nhưng cách tốt nhất để thực hiện chức năng "trang trước" hoặc thậm chí là "chuyển đến trang" là gì? Không có ví dụ IndexSearcher.searchBefore.

Tôi đang xem xét xác định tổng số trang đã cho kích thước trang và giữ một mảng ScoreDoc[] để theo dõi "sau" ScoreDoc cho mỗi trang (mảng sẽ được điền là kết quả được phân trang). Điều này sẽ cho phép tôi sử dụng "gần nhất" ScoreDoc để sử dụng trong IndexSearcher.searchAfter (hoặc null trong trường hợp xấu nhất).

Điều này có hợp lý không? Có cách tiếp cận tốt hơn không?

+0

Xin chào, Bạn có thể giải thích về việc phân trang trong phần 4.x và tôi cũng phải đối mặt với cùng một vấn đề không .. –

+0

Tôi đã sử dụng cách tiếp cận được thảo luận trong đoạn 3 ở trên. Nó hoạt động khá tốt ngoại trừ phân trang rất sâu (không ngạc nhiên). – hudsonb

Trả lời

11

Tôi đã sử dụng Lucene 4.8 và đã làm việc trên giao diện REST bao gồm phân trang. Giải pháp của tôi là sử dụng một TopScoreDocCollector và gọi phương thức topDocs (int startIndex, int numberOfhits). Chỉ số bắt đầu được tính bằng cách nhân số trang không dựa trên số lần truy cập.

... 
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); 
... 

Vì vậy, giao diện REST của tôi chấp nhận số trang và số lần truy cập trên mỗi trang làm thông số. Vì vậy, việc chuyển tiếp hoặc quay trở lại đơn giản như gửi yêu cầu mới với giá trị thích hợp cho trang

+0

Cảm ơn Jaimie, tôi thích cách tiếp cận này. – hudsonb

4

Tôi đồng ý với giải pháp được giải thích bởi Jaimie. Nhưng tôi muốn chỉ ra một khía cạnh khác mà bạn phải biết và giúp hiểu cơ chế chung của một công cụ tìm kiếm.

Với TopDocCollector, bạn có thể xác định số lần truy cập bạn muốn được thu thập phù hợp với truy vấn tìm kiếm của bạn, trước khi kết quả được sắp xếp theo điểm số hoặc tiêu chí sắp xếp khác.

Xem ví dụ sau:

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 

Chúng tôi nói với Lucene đây để thu thập tối đa 9999 tài liệu có chứa các cụm từ tìm kiếm 'Clone Warrior'. Điều này có nghĩa, nếu chỉ mục chứa hơn 9999 tài liệu chứa cụm từ tìm kiếm này, người thu thập sẽ dừng lại sau khi nó được lấp đầy với 9999 lượt truy cập!

Điều này có nghĩa là bạn càng chọn MAX_RESULTS càng tốt để trở thành kết quả tìm kiếm của mình. Nhưng điều này chỉ có liên quan nếu bạn mong đợi một số lượng lớn các lần truy cập. Ở phía bên kia nếu bạn tìm kiếm "luke skywalker" và bạn sẽ chỉ mong đợi một lần truy cập, hơn MAX_RESULTS cũng có thể được đặt thành 1.

Do đó, việc thay đổi MAX_RESULTS có thể ảnh hưởng đến điểm trả về. trên các lần truy cập được thu thập. Đó là thực tế để thiết lập MAX_RESULTS đến một kích thước đủ lớn để người dùng không thể tranh luận để bỏ lỡ một tài liệu cụ thể. Khái niệm này là hoàn toàn trái ngược với hành vi của một cơ sở dữ liệu SQL, mà luôn luôn xem xét các hồ bơi dữ liệu hoàn chỉnh.

Nhưng lucene cũng hỗ trợ một cơ chế khác. Bạn có thể, thay vì xác định MAX_RESULTS cho bộ sưu tập, hãy định nghĩa khoảng thời gian bạn muốn chờ kết quả. Vì vậy, ví dụ bạn có thể xác định rằng bạn luôn muốn dừng bộ thu sau 300ms. Đây là một cách tiếp cận tốt để bảo vệ ứng dụng của bạn về các vấn đề hiệu suất. Nhưng nếu bạn muốn chắc chắn rằng bạn đếm tất cả các tài liệu có liên quan hơn là bạn phải đặt tham số cho MAX_RESULTS hoặc thời gian chờ tối đa thành một giá trị vô tận.