2013-03-23 4 views
5

Я использую Lucene 4.2 и реализую разбивку на результат.Lucene 4 Pagination

IndexSearcher.searchAfter обеспечивает эффективный способ реализации функциональности «следующей страницы», но как лучше всего реализовать функциональность «предыдущая страница» или даже «перейти на страницу»? Например, нет IndexSearcher.searchBefore.

Я рассматривал возможность определения общего количества страниц с указанием размера страницы и хранения массива ScoreDoc[] для отслеживания «после» ScoreDoc для каждой страницы (массив будет заполнен по результатам поиска). Это позволило бы мне использовать «ближайший» ScoreDoc для использования в IndexSearcher.searchAfter (или нулевой в худшем случае).

Имеет ли это смысл? Есть ли лучший подход?

+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 принимает параметры страницы и количество обращений на страницу в качестве параметров. Так что вперед или назад так же просто, как отправить новый запрос с соответствующей стоимостью для страницы

+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 

Мы говорим Lucene здесь, чтобы собрать максимум 9999 документов, содержащих искомую фразу «Clone Warrior». Это означает, что если индекс содержит более 9999 документов, содержащих эту поисковую фразу, сборщик остановится после заполнения 9999 хитов!

Это означает, что чем больше вы выбираете MAX_RESULTS, тем лучше ваш результат поиска. Но это актуально только в том случае, если вы ожидаете большого количества обращений. С другой стороны, если вы ищете «Люк Скайуокер» и вы будете ожидать только один удар, чем MAX_RESULTS также может быть установлен в 1.

Так изменение MAX_RESULTS может повлиять на возвращаемый scoreDocs, как сортировка будет выполняться по собранным хитам. Фактически, MAX_RESULTS должен установить размер, который достаточно велик, чтобы пользователь не мог пропустить определенный документ. Эта концепция полностью противоречит поведению базы данных SQL, которая всегда учитывает полный пул данных.

Но lucene также поддерживает другой механизм. Вы можете вместо определения MAX_RESULTS для коллектора определить количество времени, которое вы хотите подождать для набора результатов. Так, например, вы можете определить, что вы всегда хотите остановить сборщик после 300 мс. Это хороший подход для защиты вашего приложения от проблем с производительностью. Но если вы хотите удостовериться, что вы считаете все соответствующие документы, чем вам нужно установить параметр для MAX_RESULTS или максимальное время ожидания до бесконечного значения.