Урок 4. Выделите фрагменты, в которых была найдена искомая фраза
Поиск по слову или фразе имеет две цели: выяснить, в каком документе он может быть найден, но также узнать, в каком фрагменте документа был найден ответ. Есть два вспомогательных класса, которые показывают попадания документа:
- org.apache.lucene.search.TopDocs — содержит ссылки на главные документы, возвращаемые поиском. Методы TopDocs :
- totalHits — количество документов, соответствующих запросу
- ScoreDocs — массив экземпляров ScoreDoc, содержащих результаты
- getMaxScore () — возвращает лучший результат из всех матчей
- org.apache.lucene.search.ScoreDoc — представляет один результат поиска. Методы ScoreDoc :
- doc — идентификатор документа
- оценка — оценка документа
Чтобы извлечь фрагмент, в котором была найдена фраза / слово, используется класс Highlighter. Пакет выделения содержит классы для предоставления функций «ключевое слово в контексте», которые обычно используются для выделения условий поиска в тексте страниц результатов. Класс Highlighter является центральным компонентом и может использоваться для выделения наиболее интересных разделов фрагмента текста и выделения их с помощью Fragmenter.
Листинг 4.1. Получение совпадений документа с искомой фразой
public static String processResults(IndexReader reader, IndexSearcher searcher, Analyzer analyzer, Query query, TopScoreDocCollector collector) throws Exception { StringBuffer answer = new StringBuffer(); SimpleHTMLFormatter htmlFormatter = new SimpleHTMLFormatter(); Highlighter highlighter = new Highlighter(htmlFormatter, new QueryScorer(query)); highlighter.setEncoder(new SimpleHTMLEncoder()); ScoreDoc[] hits = collector.topDocs().scoreDocs; //obtaining document hits of the search phrase searcher.search(query, ISearchConstants.MAXIMUM_RESULTS_PER_SEARCH); answer.append("Number of documents where it was found : ") .append(collector.getTotalHits()).append("\n"); answer.append("\n----------------------------------------------------\n"); for (int i = 0; i < hits.length; i++) { Document doc = reader.document(hits[i].doc); answer.append("Document where phrase or part of it was found and its scoring : "); answer.append(doc.get("file")).append(" (").append(hits[i].score) .append(")").append("\n"); answer.append("\n-----------------------------------------------\n"); answer.append(searchInContent(highlighter, reader, doc, i, ISearchConstants.FIELD_ABSTRACT_TEXT, analyzer)); answer.append(searchInContent(highlighter, reader, doc, i, ISearchConstants.FIELD_TEXT, analyzer)); answer.append("\n------------------------------------------------\n"); } return answer.toString(); }
Анализаторы возвращают TokenStream; TokenStream, полученный анализатором, будет использоваться для выделения фрагментов.
Кроме того, созданный выше объект Highlighter может использоваться для извлечения фрагмента, в котором была найдена фраза / слово:
Листинг 4.2. Выделение фрагментов (сначала анализируется аннотация, затем обычный индексированный текст)
private static String searchInContent(Highlighter highlighter, IndexReader indexReader, Document doc, Integer docId, String contentOption, Analyzer analyzer) throws Exception { StringBuffer answer = new StringBuffer(); String text = doc.get(contentOption); TokenStream tokenStream = TokenSources.getAnyTokenStream(indexReader, docId, contentOption, analyzer); //try to get the best matching fragment(s) try { TextFragment[] frag = highlighter.getBestTextFragments(tokenStream, text, false, ISearchConstants.MAXIMUM_RESULTS_PER_SEARCH); for (int j = 0; j < frag.length; j++) { answer.append(SearchUtils.processText(frag[j], (contentOption .equals(ISearchConstants.FIELD_ABSTRACT_TEXT) ? true : false), j+1)); } } catch (InvalidTokenOffsetsException ex) { ex.printStackTrace(); TextFragment frag = new TextFragment(text, 0, 10); answer.append(SearchUtils.processText(frag, (contentOption .equals(ISearchConstants.FIELD_ABSTRACT_TEXT) ? true : false), 1)); } return answer.toString(); }
Личное примечание: при индексации документов старайтесь избегать документов, содержащих изображения; класс Highlighter не может выполнить извлечение фрагмента этих документов, и будет выдано исключение InvalidTokendOffsetsException.
Ресурсы
Учить
- Посетите Apache.org/tika, чтобы узнать больше.
- Посетите Apache.org/Lucene, чтобы узнать больше.