Index: lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java =================================================================== --- lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java (revision 1457977) +++ lucene/highlighter/src/java/org/apache/lucene/search/postingshighlight/PostingsHighlighter.java (working copy) @@ -237,16 +237,39 @@ * {@link IndexOptions#DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS} */ public Map highlightFields(String fields[], Query query, IndexSearcher searcher, TopDocs topDocs, int maxPassages) throws IOException { + final ScoreDoc scoreDocs[] = topDocs.scoreDocs; + int docids[] = new int[scoreDocs.length]; + for (int i = 0; i < docids.length; i++) { + docids[i] = scoreDocs[i].doc; + } + + return highlightFields(fields, query, searcher, docids, maxPassages); + } + + /** + * Highlights the top-N passages from multiple fields, + * for the provided int[] docids. + * + * @param fields field names to highlight. + * Must have a stored string value and also be indexed with offsets. + * @param query query to highlight. + * @param searcher searcher that was previously used to execute the query. + * @param int[] docids containing the document IDs to highlight. + * @param maxPassages The maximum number of top-N ranked passages per-field used to + * form the highlighted snippets. + * @return Map keyed on field name, containing the array of formatted snippets + * corresponding to the documents in topDocs. + * If no highlights were found for a document, its value is null. + * @throws IOException if an I/O error occurred during processing + * @throws IllegalArgumentException if field was indexed without + * {@link IndexOptions#DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS} + */ + public Map highlightFields(String fields[], Query query, IndexSearcher searcher, int[] docids, int maxPassages) throws IOException { final IndexReader reader = searcher.getIndexReader(); - final ScoreDoc scoreDocs[] = topDocs.scoreDocs; query = rewrite(query); SortedSet queryTerms = new TreeSet(); query.extractTerms(queryTerms); - int docids[] = new int[scoreDocs.length]; - for (int i = 0; i < docids.length; i++) { - docids[i] = scoreDocs[i].doc; - } IndexReaderContext readerContext = reader.getContext(); List leaves = readerContext.leaves(); @@ -277,15 +300,15 @@ Term terms[] = fieldTerms.toArray(new Term[fieldTerms.size()]); Map fieldHighlights = highlightField(field, contents[i], bi, terms, docids, leaves, maxPassages); - String[] result = new String[scoreDocs.length]; - for (int j = 0; j < scoreDocs.length; j++) { - result[j] = fieldHighlights.get(scoreDocs[j].doc); + String[] result = new String[docids.length]; + for (int j = 0; j < docids.length; j++) { + result[j] = fieldHighlights.get(docids[j]); } highlights.put(field, result); } return highlights; } - + private Map highlightField(String field, String contents[], BreakIterator bi, Term terms[], int[] docids, List leaves, int maxPassages) throws IOException { Map highlights = new HashMap(); Index: lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java =================================================================== --- lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java (revision 1457977) +++ lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestPostingsHighlighter.java (working copy) @@ -39,6 +39,7 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.Query; +import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.Sort; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TopDocs; @@ -465,4 +466,42 @@ ir.close(); dir.close(); } + + public void testSpecificDocIDs() throws Exception { + Directory dir = newDirectory(); + IndexWriterConfig iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())); + iwc.setMergePolicy(newLogMergePolicy()); + RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwc); + + FieldType offsetsType = new FieldType(TextField.TYPE_STORED); + offsetsType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); + Field body = new Field("body", "", offsetsType); + Document doc = new Document(); + doc.add(body); + + body.setStringValue("This is a test. Just a test highlighting from postings. Feel free to ignore."); + iw.addDocument(doc); + body.setStringValue("Highlighting the first term. Hope it works."); + iw.addDocument(doc); + + IndexReader ir = iw.getReader(); + iw.close(); + + IndexSearcher searcher = newSearcher(ir); + PostingsHighlighter highlighter = new PostingsHighlighter(); + Query query = new TermQuery(new Term("body", "highlighting")); + TopDocs topDocs = searcher.search(query, null, 10, Sort.INDEXORDER); + assertEquals(2, topDocs.totalHits); + ScoreDoc[] hits = topDocs.scoreDocs; + int[] docIDs = new int[2]; + docIDs[0] = hits[0].doc; + docIDs[1] = hits[1].doc; + String snippets[] = highlighter.highlightFields(new String[] {"body"}, query, searcher, docIDs, 1).get("body"); + assertEquals(2, snippets.length); + assertEquals("Just a test highlighting from postings. ", snippets[0]); + assertEquals("Highlighting the first term. ", snippets[1]); + + ir.close(); + dir.close(); + } }