Index: src/test/org/apache/lucene/search/TestSort.java =================================================================== --- src/test/org/apache/lucene/search/TestSort.java (revision 726211) +++ src/test/org/apache/lucene/search/TestSort.java (working copy) @@ -120,6 +120,8 @@ throws IOException { RAMDirectory indexStore = new RAMDirectory (); IndexWriter writer = new IndexWriter (indexStore, new SimpleAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); + writer.setMaxBufferedDocs(2); + writer.setMergeFactor(1000); for (int i=0; i 0 ) { try { Thread.sleep(slowdown); @@ -315,8 +317,8 @@ System.out.println("caught " + x); } } - bits.set( doc ); - lastDocCollected = doc; + bits.set( docId ); + lastDocCollected = docId; } public int hitCount() { @@ -326,6 +328,10 @@ public int getLastDocCollected() { return lastDocCollected; } + + public void setDocBase(int base) { + this.base = base; + } } Index: src/test/org/apache/lucene/search/TestTermScorer.java =================================================================== --- src/test/org/apache/lucene/search/TestTermScorer.java (revision 726211) +++ src/test/org/apache/lucene/search/TestTermScorer.java (working copy) @@ -82,15 +82,19 @@ //must call next first - ts.score(new HitCollector() + ts.score(new DocCollector() { + private int base; public void collect(int doc, float score) { - docs.add(new TestHit(doc, score)); + docs.add(new TestHit(doc + base, score)); assertTrue("score " + score + " is not greater than 0", score > 0); assertTrue("Doc: " + doc + " does not equal: " + 0 + " or doc does not equaal: " + 5, doc == 0 || doc == 5); } + public void setDocBase(int base) { + this.base = base; + } }); assertTrue("docs Size: " + docs.size() + " is not: " + 2, docs.size() == 2); TestHit doc0 = (TestHit) docs.get(0); Index: src/test/org/apache/lucene/search/TestSetNorm.java =================================================================== --- src/test/org/apache/lucene/search/TestSetNorm.java (revision 726211) +++ src/test/org/apache/lucene/search/TestSetNorm.java (working copy) @@ -62,10 +62,14 @@ new IndexSearcher(store).search (new TermQuery(new Term("field", "word")), - new HitCollector() { + new DocCollector() { + private int base; public final void collect(int doc, float score) { - scores[doc] = score; + scores[doc + base] = score; } + public void setDocBase(int base) { + this.base = base; + } }); float lastScore = 0.0f; Index: src/test/org/apache/lucene/search/TestScorerPerf.java =================================================================== --- src/test/org/apache/lucene/search/TestScorerPerf.java (revision 726211) +++ src/test/org/apache/lucene/search/TestScorerPerf.java (working copy) @@ -96,17 +96,22 @@ return sets; } - public static class CountingHitCollector extends HitCollector { + public static class CountingHitCollector extends DocCollector { int count=0; int sum=0; + private int docBase; public void collect(int doc, float score) { count++; - sum += doc; // use it to avoid any possibility of being optimized away + sum += doc + docBase; // use it to avoid any possibility of being optimized away } public int getCount() { return count; } public int getSum() { return sum; } + + public void setDocBase(int base) { + this.docBase = base; + } } Index: src/test/org/apache/lucene/search/TestSimilarity.java =================================================================== --- src/test/org/apache/lucene/search/TestSimilarity.java (revision 726211) +++ src/test/org/apache/lucene/search/TestSimilarity.java (working copy) @@ -75,10 +75,11 @@ searcher.search (new TermQuery(b), - new HitCollector() { + new DocCollector() { public final void collect(int doc, float score) { assertTrue(score == 1.0f); } + public void setDocBase(int base) {} }); BooleanQuery bq = new BooleanQuery(); @@ -87,11 +88,15 @@ //System.out.println(bq.toString("field")); searcher.search (bq, - new HitCollector() { + new DocCollector() { + private int base; public final void collect(int doc, float score) { //System.out.println("Doc=" + doc + " score=" + score); - assertTrue(score == (float)doc+1); + assertTrue(score == (float)doc+base+1); } + public void setDocBase(int base) { + this.base = base; + } }); PhraseQuery pq = new PhraseQuery(); @@ -100,22 +105,24 @@ //System.out.println(pq.toString("field")); searcher.search (pq, - new HitCollector() { + new DocCollector() { public final void collect(int doc, float score) { //System.out.println("Doc=" + doc + " score=" + score); assertTrue(score == 1.0f); } + public void setDocBase(int base) {} }); pq.setSlop(2); //System.out.println(pq.toString("field")); searcher.search (pq, - new HitCollector() { + new DocCollector() { public final void collect(int doc, float score) { //System.out.println("Doc=" + doc + " score=" + score); assertTrue(score == 2.0f); } + public void setDocBase(int base) {} }); } } Index: src/test/org/apache/lucene/search/TestDocBoost.java =================================================================== --- src/test/org/apache/lucene/search/TestDocBoost.java (revision 726211) +++ src/test/org/apache/lucene/search/TestDocBoost.java (working copy) @@ -65,10 +65,14 @@ new IndexSearcher(store).search (new TermQuery(new Term("field", "word")), - new HitCollector() { + new DocCollector() { + private int base; public final void collect(int doc, float score) { - scores[doc] = score; + scores[doc + base] = score; } + public void setDocBase(int base) { + this.base = base; + } }); float lastScore = 0.0f; Index: src/test/org/apache/lucene/search/QueryUtils.java =================================================================== --- src/test/org/apache/lucene/search/QueryUtils.java (revision 726211) +++ src/test/org/apache/lucene/search/QueryUtils.java (working copy) @@ -151,8 +151,10 @@ final int[] sdoc = new int[] {-1}; final float maxDiff = 1e-5f; - s.search(q,new HitCollector() { + s.search(q,new DocCollector() { + private int base; public void collect(int doc, float score) { + doc = doc + base; try { int op = order[(opidx[0]++)%order.length]; //System.out.println(op==skip_op ? "skip("+(sdoc[0]+1)+")":"next()"); @@ -183,6 +185,9 @@ throw new RuntimeException(e); } } + public void setDocBase(int base) { + this.base = base; + } }); // make sure next call to scorer is false. @@ -198,9 +203,11 @@ //System.out.println("checkFirstSkipTo: "+q); final float maxDiff = 1e-5f; final int lastDoc[] = {-1}; - s.search(q,new HitCollector() { + s.search(q,new DocCollector() { + private int base; public void collect(int doc, float score) { //System.out.println("doc="+doc); + doc = doc + base; try { for (int i=lastDoc[0]+1; i<=doc; i++) { Weight w = q.weight(s); @@ -216,6 +223,9 @@ throw new RuntimeException(e); } } + public void setDocBase(int base) { + this.base = base; + } }); Weight w = q.weight(s); Scorer scorer = w.scorer(s.getIndexReader()); Index: src/test/org/apache/lucene/index/TestOmitTf.java =================================================================== --- src/test/org/apache/lucene/index/TestOmitTf.java (revision 726211) +++ src/test/org/apache/lucene/index/TestOmitTf.java (working copy) @@ -26,7 +26,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.HitCollector; +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Searcher; import org.apache.lucene.search.Similarity; @@ -348,16 +348,21 @@ dir.close(); } - public static class CountingHitCollector extends HitCollector { + public static class CountingHitCollector extends DocCollector { static int count=0; static int sum=0; + private int docBase; CountingHitCollector(){count=0;sum=0;} public void collect(int doc, float score) { count++; - sum += doc; // use it to avoid any possibility of being optimized away + sum += doc + docBase; // use it to avoid any possibility of being optimized away } public static int getCount() { return count; } public static int getSum() { return sum; } + + public void setDocBase(int base) { + this.docBase = base; + } } } Index: src/test/org/apache/lucene/index/TestIndexReaderReopen.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexReaderReopen.java (revision 726211) +++ src/test/org/apache/lucene/index/TestIndexReaderReopen.java (working copy) @@ -320,7 +320,7 @@ assertRefCountEquals(1, reader0); assertTrue(reader0 instanceof MultiSegmentReader); - SegmentReader[] subReaders0 = ((MultiSegmentReader) reader0).getSubReaders(); + IndexReader[] subReaders0 = ((MultiSegmentReader) reader0).getSequentialReaders(); for (int i = 0; i < subReaders0.length; i++) { assertRefCountEquals(1, subReaders0[i]); } @@ -332,7 +332,7 @@ IndexReader reader1 = refreshReader(reader0, true).refreshedReader; assertTrue(reader1 instanceof MultiSegmentReader); - SegmentReader[] subReaders1 = ((MultiSegmentReader) reader1).getSubReaders(); + IndexReader[] subReaders1 = ((MultiSegmentReader) reader1).getSequentialReaders(); assertEquals(subReaders0.length, subReaders1.length); for (int i = 0; i < subReaders0.length; i++) { @@ -349,7 +349,7 @@ IndexReader reader2 = refreshReader(reader1, true).refreshedReader; assertTrue(reader2 instanceof MultiSegmentReader); - SegmentReader[] subReaders2 = ((MultiSegmentReader) reader2).getSubReaders(); + IndexReader[] subReaders2 = ((MultiSegmentReader) reader2).getSequentialReaders(); assertEquals(subReaders1.length, subReaders2.length); for (int i = 0; i < subReaders2.length; i++) { @@ -373,7 +373,7 @@ IndexReader reader3 = refreshReader(reader0, true).refreshedReader; assertTrue(reader3 instanceof MultiSegmentReader); - SegmentReader[] subReaders3 = ((MultiSegmentReader) reader3).getSubReaders(); + IndexReader[] subReaders3 = ((MultiSegmentReader) reader3).getSequentialReaders(); assertEquals(subReaders3.length, subReaders0.length); // try some permutations @@ -945,14 +945,14 @@ if (checkSubReaders) { if (reader instanceof MultiSegmentReader) { - SegmentReader[] subReaders = ((MultiSegmentReader) reader).getSubReaders(); + IndexReader[] subReaders = ((MultiSegmentReader) reader).getSequentialReaders(); for (int i = 0; i < subReaders.length; i++) { assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed); } } if (reader instanceof MultiReader) { - IndexReader[] subReaders = ((MultiReader) reader).getSubReaders(); + IndexReader[] subReaders = ((MultiReader) reader).getSequentialReaders(); for (int i = 0; i < subReaders.length; i++) { assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed); } @@ -971,7 +971,7 @@ reader.ensureOpen(); if (reader instanceof MultiSegmentReader) { - SegmentReader[] subReaders = ((MultiSegmentReader) reader).getSubReaders(); + IndexReader[] subReaders = ((MultiSegmentReader) reader).getSequentialReaders(); for (int i = 0; i < subReaders.length; i++) { assertReaderOpen(subReaders[i]); } Index: src/java/org/apache/lucene/search/TopFieldValueDocCollector.java =================================================================== --- src/java/org/apache/lucene/search/TopFieldValueDocCollector.java (revision 0) +++ src/java/org/apache/lucene/search/TopFieldValueDocCollector.java (revision 0) @@ -0,0 +1,115 @@ +package org.apache.lucene.search; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; + +import org.apache.lucene.index.IndexReader; + +public class TopFieldValueDocCollector extends DocCollector { + + private final ByValueFieldSortedHitQueue queue; + + private final FieldComparator[] comparators; + + private int subReaderIndex = -1; + + private final int numHits; + private int totalHits; + + // TODO: remove + public void setDocBase(int docBase) {} + + public TopFieldValueDocCollector(Sort sort, int numHits) + throws IOException { + queue = new ByValueFieldSortedHitQueue(sort.fields, numHits); + comparators = queue.comparators; + this.numHits = numHits; + } + + public void setNextReader(IndexReader reader) throws IOException { + //System.out.println("now set next reader"); + subReaderIndex++; + for(int i=0;iWhen this method is used the {@link #explain(int)} method should not be used. */ - public void score(HitCollector hc) throws IOException { + public void score(DocCollector hc) throws IOException { if (allowDocsOutOfOrder && requiredScorers.size() == 0 && prohibitedScorers.size() < 32) { // fall back to BooleanScorer, scores documents somewhat out of order @@ -326,11 +326,11 @@ *
Note that {@link #next()} must be called once before this method is * called for the first time. * @param hc The collector to which all matching documents are passed through - * {@link HitCollector#collect(int, float)}. + * {@link DocCollector#collect(int, float)}. * @param max Do not score documents past this. * @return true if more matching documents may remain. */ - protected boolean score(HitCollector hc, int max) throws IOException { + protected boolean score(DocCollector hc, int max) throws IOException { // null pointer exception when next() was not called before: int docNr = countingSumScorer.doc(); while (docNr < max) { Index: src/java/org/apache/lucene/search/Searcher.java =================================================================== --- src/java/org/apache/lucene/search/Searcher.java (revision 726211) +++ src/java/org/apache/lucene/search/Searcher.java (working copy) @@ -88,7 +88,7 @@ /** Lower-level search API. * - *

{@link HitCollector#collect(int,float)} is called for every matching + *

{@link DocCollector#collect(int,float)} is called for every matching * document. * *

Applications should only use this if they need all of the @@ -100,14 +100,14 @@ * between 0 and 1. * @throws BooleanQuery.TooManyClauses */ - public void search(Query query, HitCollector results) + public void search(Query query, DocCollector results) throws IOException { search(query, (Filter)null, results); } /** Lower-level search API. * - *

{@link HitCollector#collect(int,float)} is called for every matching + *

{@link DocCollector#collect(int,float)} is called for every matching * document. *
HitCollector-based access to remote indexes is discouraged. * @@ -121,7 +121,7 @@ * @param results to receive hits * @throws BooleanQuery.TooManyClauses */ - public void search(Query query, Filter filter, HitCollector results) + public void search(Query query, Filter filter, DocCollector results) throws IOException { search(createWeight(query), filter, results); } @@ -197,7 +197,7 @@ /* The following abstract methods were added as a workaround for GCJ bug #15411. * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15411 */ - abstract public void search(Weight weight, Filter filter, HitCollector results) throws IOException; + abstract public void search(Weight weight, Filter filter, DocCollector results) throws IOException; abstract public void close() throws IOException; abstract public int docFreq(Term term) throws IOException; abstract public int maxDoc() throws IOException; Index: src/java/org/apache/lucene/search/TopDocCollector.java =================================================================== --- src/java/org/apache/lucene/search/TopDocCollector.java (revision 726211) +++ src/java/org/apache/lucene/search/TopDocCollector.java (working copy) @@ -19,13 +19,14 @@ import org.apache.lucene.util.PriorityQueue; -/** A {@link HitCollector} implementation that collects the top-scoring +/** A {@link DocCollector implementation that collects the top-scoring * documents, returning them as a {@link TopDocs}. This is used by {@link * IndexSearcher} to implement {@link TopDocs}-based search. * *

This may be extended, overriding the collect method to, e.g., * conditionally invoke super() in order to filter which * documents are collected. + * **/ public class TopDocCollector extends HitCollector { @@ -36,6 +37,8 @@ /** The priority queue which holds the top-scoring documents. */ protected PriorityQueue hq; + + private int docBase; /** Construct to collect a given number of hits. * @param numHits the maximum number of hits to collect @@ -63,12 +66,12 @@ if (score > 0.0f) { totalHits++; if (reusableSD == null) { - reusableSD = new ScoreDoc(doc, score); + reusableSD = new ScoreDoc(doc + docBase, score); } else if (score >= reusableSD.score) { // reusableSD holds the last "rejected" entry, so, if // this new score is not better than that, there's no // need to try inserting it - reusableSD.doc = doc; + reusableSD.doc = doc + docBase; reusableSD.score = score; } else { return; @@ -92,4 +95,8 @@ return new TopDocs(totalHits, scoreDocs, maxScore); } + + public void setDocBase(int base) { + this.docBase = base; + } } Index: src/java/org/apache/lucene/search/ByValueFieldSortedHitQueue.java =================================================================== --- src/java/org/apache/lucene/search/ByValueFieldSortedHitQueue.java (revision 0) +++ src/java/org/apache/lucene/search/ByValueFieldSortedHitQueue.java (revision 0) @@ -0,0 +1,148 @@ +package org.apache.lucene.search; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.util.PriorityQueue; + +import java.io.IOException; +import java.text.Collator; +import java.util.Locale; + +/** + * Expert: A hit queue for sorting by hits by terms in more than one field. + * Uses FieldCache.DEFAULT for maintaining internal term lookup tables. + * + *

Created: Dec 8, 2003 12:56:03 PM + * + * @since lucene 1.4 + * @version $Id: FieldSortedHitQueue.java 724484 2008-12-08 21:07:45Z mikemccand $ + * @see Searcher#search(Query,Filter,int,Sort) + * @see FieldCache + */ +public class ByValueFieldSortedHitQueue extends PriorityQueue { + + final static class Entry { + int slot; + int subReaderIndex; + int subDocID; + float score; + Entry(int slot, int subReaderIndex, int subDocID, float score) { + this.slot = slot; + this.subReaderIndex = subReaderIndex; + this.subDocID = subDocID; + this.score = score; + } + } + + /** + * Creates a hit queue sorted by the given list of fields. + * @param fields Fieldable names, in priority order (highest priority first). Cannot be null or empty. + * @param size The number of hits to retain. Must be greater than zero. + * @throws IOException + */ + public ByValueFieldSortedHitQueue(SortField[] fields, int size) throws IOException { + final int n = fields.length; + comparators = new FieldComparator[n]; + + this.fields = fields; + for (int i=0; ia is less relevant than b. + * @param a ScoreDoc + * @param b ScoreDoc + * @return true if document a should be sorted after document b. + */ + protected boolean lessThan (final Object a, final Object b) { + final Entry hitA = (Entry) a; + final Entry hitB = (Entry) b; + + // run comparators + final int n = comparators.length; + int c = 0; + for (int i=0; i hitB.subReaderIndex || + (hitA.subReaderIndex == hitB.subReaderIndex && + hitA.subDocID > hitB.subDocID); + + return c > 0; + } + + + /** + * Given a FieldDoc object, stores the values used + * to sort the given document. These values are not the raw + * values out of the index, but the internal representation + * of them. This is so the given search hit can be collated + * by a MultiSearcher with other search hits. + * @param doc The FieldDoc to store sort values into. + * @return The same FieldDoc passed in. + * @see Searchable#search(Weight,Filter,int,Sort) + */ + FieldDoc fillFields (final Entry entry, int[] starts) { + final int n = comparators.length; + final Comparable[] fields = new Comparable[n]; + for (int i=0; i 1.0f) doc.score /= maxscore; // normalize scores + return new FieldDoc(entry.subDocID + starts[entry.subReaderIndex], + entry.score, + fields); + } + + + /** Returns the SortFields being used by this hit queue. */ + SortField[] getFields() { + return fields; + } + + static FieldComparator getCachedComparator (String field, int type, int numHits) throws IOException { + if (type == SortField.SCORE) + return new FieldComparator.RelevanceComparator(numHits); + else if (type == SortField.DOC) + return new FieldComparator.DocComparator(numHits); + else if (type == SortField.INT) + return new FieldComparator.IntComparator(numHits, field); + else + // TODO: all other types + throw new RuntimeException("not done yet: " + type); + } +} Property changes on: src/java/org/apache/lucene/search/ByValueFieldSortedHitQueue.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/java/org/apache/lucene/search/DocCollector.java =================================================================== --- src/java/org/apache/lucene/search/DocCollector.java (revision 0) +++ src/java/org/apache/lucene/search/DocCollector.java (revision 0) @@ -0,0 +1,69 @@ +package org.apache.lucene.search; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Lower-level search API. + *
DocCollectors are primarily meant to be used to implement queries, + * sorting and filtering. + * @see Searcher#search(Query,DocCollector) + */ + +import java.io.IOException; + +import org.apache.lucene.index.IndexReader; + +public abstract class DocCollector { + /** Called once for every document matching a query, with the document + * number and its raw score. + * + *

If, for example, an application wished to collect all of the hits for a + * query in a BitSet, then it might:

+   *   Searcher searcher = new IndexSearcher(indexReader);
+   *   final BitSet bits = new BitSet(indexReader.maxDoc());
+   *   searcher.search(query, new HitCollector() {
+   *       public void collect(int doc, float score) {
+   *         bits.set(doc);
+   *       }
+   *     });
+   * 
+ * + *

Note: This is called in an inner search loop. For good search + * performance, implementations of this method should not call + * {@link Searcher#doc(int)} or + * {@link org.apache.lucene.index.IndexReader#document(int)} on every + * document number encountered. Doing so can slow searches by an order + * of magnitude or more. + *

Note: The score passed to this method is a raw score. + * In other words, the score will not necessarily be a float whose value is + * between 0 and 1. + */ + public abstract void collect(int doc, float score); + + /** + * Sets the base value added to doc in collect. Used to collect across + * multiple IndexReaders. + * + * @param base + */ + public abstract void setDocBase(int base); + + // TODO: make abstract, replaces setDocBase + public void setNextReader(IndexReader reader) throws IOException + { + } +} Property changes on: src/java/org/apache/lucene/search/DocCollector.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/java/org/apache/lucene/search/Searchable.java =================================================================== --- src/java/org/apache/lucene/search/Searchable.java (revision 726211) +++ src/java/org/apache/lucene/search/Searchable.java (working copy) @@ -38,7 +38,7 @@ public interface Searchable extends java.rmi.Remote { /** Lower-level search API. * - *

{@link HitCollector#collect(int,float)} is called for every non-zero + *

{@link DocCollector#collect(int,float)} is called for every non-zero * scoring document. *
HitCollector-based access to remote indexes is discouraged. * @@ -52,7 +52,7 @@ * @param results to receive hits * @throws BooleanQuery.TooManyClauses */ - void search(Weight weight, Filter filter, HitCollector results) + void search(Weight weight, Filter filter, DocCollector results) throws IOException; @@ -92,7 +92,7 @@ TopDocs search(Weight weight, Filter filter, int n) throws IOException; /** Expert: Returns the stored fields of document i. - * Called by {@link HitCollector} implementations. + * Called by {@link DocCollector} implementations. * @see IndexReader#document(int) * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error Index: src/java/org/apache/lucene/search/HitCollector.java =================================================================== --- src/java/org/apache/lucene/search/HitCollector.java (revision 726211) +++ src/java/org/apache/lucene/search/HitCollector.java (working copy) @@ -22,8 +22,9 @@ * sorting and filtering. * @see Searcher#search(Query,HitCollector) * @version $Id$ + * @deprecated use {link: {@link DocCollector} */ -public abstract class HitCollector { +public abstract class HitCollector extends DocCollector{ /** Called once for every document matching a query, with the document * number and its raw score. * @@ -49,4 +50,14 @@ * between 0 and 1. */ public abstract void collect(int doc, float score); + + /** + * Sets the base value added to doc in collect. Used to collect across + * multiple IndexReaders. + * + * @param base + */ + public void setDocBase(int base) { + throw new UnsupportedOperationException(); + } } Index: src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== --- src/java/org/apache/lucene/search/BooleanQuery.java (revision 726211) +++ src/java/org/apache/lucene/search/BooleanQuery.java (working copy) @@ -326,7 +326,7 @@ * *

* Specifics: By setting this option to true, calls to - * {@link HitCollector#collect(int,float)} might be + * {@link DocCollector#collect(int,float)} might be * invoked first for docid N and only later for docid N-1. * Being static, this setting is system wide. *

Index: src/java/org/apache/lucene/search/FieldComparator.java =================================================================== --- src/java/org/apache/lucene/search/FieldComparator.java (revision 0) +++ src/java/org/apache/lucene/search/FieldComparator.java (revision 0) @@ -0,0 +1,161 @@ +package org.apache.lucene.search; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; + +import org.apache.lucene.index.IndexReader; + +public abstract class FieldComparator { + + public static final class RelevanceComparator extends FieldComparator { + + // nocommit -- maybe "setcurrentscoredoc"? + + private final float[] scores; + + RelevanceComparator(int numHits) { + scores = new float[numHits]; + } + + public void setNextReader(IndexReader reader) { + } + + public int compare(int slot, int doc, float score) { + if (scores[slot] > score) return -1; + if (scores[slot] < score) return 1; + return 0; + } + + public int compare(int slot1, int slot2) { + if (scores[slot1] > scores[slot2]) return -1; + if (scores[slot1] < scores[slot2]) return 1; + return 0; + } + + public Comparable value(int slot) { + return new Float(scores[slot]); + } + + public void copy(int slot, int doc, float score) { + scores[slot] = score; + } + + public int sortType() { + return SortField.SCORE; + } + }; + + public static final class DocComparator extends FieldComparator { + + // nocommit -- maybe "setcurrentscoredoc"? + + private final int[] docIDs; + private int docBase; + private int readerMaxDoc; + + DocComparator(int numHits) { + docIDs = new int[numHits]; + } + + public void setNextReader(IndexReader reader) { + // TODO: can we "map" our docIDs to the current + // reader? saves having to then subtract on every + // compare call + docBase += readerMaxDoc; + readerMaxDoc = reader.maxDoc(); + } + + public int compare(int slot, int doc, float score) { + final int delta = docIDs[slot] - docBase - doc; + // TODO: can we return delta directly? + if (delta > 0) return -1; + if (delta < 0) return 1; + return 0; + } + + public int compare(int slot1, int slot2) { + final int delta = docIDs[slot1] - docIDs[slot2]; + // TODO: can we return delta directly? + if (delta > 0) return -1; + if (delta < 0) return 1; + return 0; + } + + public Comparable value(int slot) { + return new Integer(docIDs[slot]); + } + + public void copy(int slot, int doc, float score) { + docIDs[slot] = docBase + doc; + } + + public int sortType() { + return SortField.SCORE; + } + }; + + public static final class IntComparator extends FieldComparator { + + // nocommit -- maybe "setcurrentscoredoc"? + + private final int[] values; + private int[] currentReaderValues; + private final String field; + + IntComparator(int numHits, String field) { + values = new int[numHits]; + this.field = field; + } + + public void setNextReader(IndexReader reader) throws IOException { + currentReaderValues = FieldCache.DEFAULT.getInts(reader, field); + } + + public int compare(int slot, int doc, float score) { + //System.out.println(" e compare slot=" + slot + " val=" + values[slot] + " doc=" + doc + " docVal=" + currentReaderValues[doc]); + return values[slot] - currentReaderValues[doc]; + } + + public int compare(int slot1, int slot2) { + //System.out.println(" x compare slot1=" + slot1 + " val1=" + values[slot1] + " slot2=" + slot2 + " val2=" + values[slot2]); + return values[slot1] - values[slot2]; + } + + public Comparable value(int slot) { + return new Integer(values[slot]); + } + + public void copy(int slot, int doc, float score) { + values[slot] = currentReaderValues[doc]; + //System.out.println(" copy doc=" + doc + " slot=" + slot + " docVal=" + currentReaderValues[doc]); + } + + public int sortType() { + return SortField.INT; + } + }; + + public abstract void setNextReader(IndexReader reader) throws IOException; + // nocommit -- allowed to return -X or only -1 (and X, 1)??? + public abstract int compare(int slot, int doc, float score); + public abstract int compare(int slot1, int slot2); + public abstract Comparable value(int slot); + public abstract void copy(int slot, int doc, float score); + public abstract int sortType(); +} Property changes on: src/java/org/apache/lucene/search/FieldComparator.java ___________________________________________________________________ Name: svn:eol-style + native Index: src/java/org/apache/lucene/search/DisjunctionSumScorer.java =================================================================== --- src/java/org/apache/lucene/search/DisjunctionSumScorer.java (revision 726211) +++ src/java/org/apache/lucene/search/DisjunctionSumScorer.java (working copy) @@ -112,10 +112,10 @@ /** Scores and collects all matching documents. * @param hc The collector to which all matching documents are passed through - * {@link HitCollector#collect(int, float)}. + * {@link DocCollector#collect(int, float)}. *
When this method is used the {@link #explain(int)} method should not be used. */ - public void score(HitCollector hc) throws IOException { + public void score(DocCollector hc) throws IOException { while (next()) { hc.collect(currentDoc, currentScore); } @@ -125,11 +125,11 @@ * Note that {@link #next()} must be called once before this method is called * for the first time. * @param hc The collector to which all matching documents are passed through - * {@link HitCollector#collect(int, float)}. + * {@link DocCollector#collect(int, float)}. * @param max Do not score documents past this. * @return true if more matching documents may remain. */ - protected boolean score(HitCollector hc, int max) throws IOException { + protected boolean score(DocCollector hc, int max) throws IOException { while (currentDoc < max) { hc.collect(currentDoc, currentScore); if (!next()) { Index: src/java/org/apache/lucene/search/Scorer.java =================================================================== --- src/java/org/apache/lucene/search/Scorer.java (revision 726211) +++ src/java/org/apache/lucene/search/Scorer.java (working copy) @@ -50,10 +50,10 @@ /** Scores and collects all matching documents. * @param hc The collector to which all matching documents are passed through - * {@link HitCollector#collect(int, float)}. + * {@link DocCollector#collect(int, float)}. *
When this method is used the {@link #explain(int)} method should not be used. */ - public void score(HitCollector hc) throws IOException { + public void score(DocCollector hc) throws IOException { while (next()) { hc.collect(doc(), score()); } @@ -63,11 +63,11 @@ * Note that {@link #next()} must be called once before this method is called * for the first time. * @param hc The collector to which all matching documents are passed through - * {@link HitCollector#collect(int, float)}. + * {@link DocCollector#collect(int, float)}. * @param max Do not score documents past this. * @return true if more matching documents may remain. */ - protected boolean score(HitCollector hc, int max) throws IOException { + protected boolean score(DocCollector hc, int max) throws IOException { while (doc() < max) { hc.collect(doc(), score()); if (!next()) @@ -84,7 +84,7 @@ /** Returns an explanation of the score for a document. *
When this method is used, the {@link #next()}, {@link #skipTo(int)} and - * {@link #score(HitCollector)} methods should not be used. + * {@link #score(DocCollector)} methods should not be used. * @param doc The document number for the explanation. */ public abstract Explanation explain(int doc) throws IOException; Index: src/java/org/apache/lucene/search/BooleanScorer.java =================================================================== --- src/java/org/apache/lucene/search/BooleanScorer.java (revision 726211) +++ src/java/org/apache/lucene/search/BooleanScorer.java (working copy) @@ -46,11 +46,11 @@ public boolean done; public boolean required = false; public boolean prohibited = false; - public HitCollector collector; + public DocCollector collector; public SubScorer next; public SubScorer(Scorer scorer, boolean required, boolean prohibited, - HitCollector collector, SubScorer next) + DocCollector collector, SubScorer next) throws IOException { this.scorer = scorer; this.done = !scorer.next(); @@ -94,12 +94,12 @@ private int end; private Bucket current; - public void score(HitCollector hc) throws IOException { + public void score(DocCollector hc) throws IOException { next(); score(hc, Integer.MAX_VALUE); } - protected boolean score(HitCollector hc, int max) throws IOException { + protected boolean score(DocCollector hc, int max) throws IOException { if (coordFactors == null) computeCoordFactors(); @@ -215,27 +215,29 @@ public final int size() { return SIZE; } - public HitCollector newCollector(int mask) { + public DocCollector newCollector(int mask) { return new Collector(mask, this); } } - static final class Collector extends HitCollector { + static final class Collector extends DocCollector { private BucketTable bucketTable; private int mask; + private int base; public Collector(int mask, BucketTable bucketTable) { this.mask = mask; this.bucketTable = bucketTable; } public final void collect(final int doc, final float score) { + int docid = doc + base; final BucketTable table = bucketTable; - final int i = doc & BucketTable.MASK; + final int i = docid & BucketTable.MASK; Bucket bucket = table.buckets[i]; if (bucket == null) table.buckets[i] = bucket = new Bucket(); - if (bucket.doc != doc) { // invalid bucket - bucket.doc = doc; // set doc + if (bucket.doc != docid) { // invalid bucket + bucket.doc = docid; // set doc bucket.score = score; // initialize score bucket.bits = mask; // initialize mask bucket.coord = 1; // initialize coord @@ -248,6 +250,9 @@ bucket.coord++; // increment coord } } + public void setDocBase(int base) { + this.base = base; + } } public boolean skipTo(int target) { Index: src/java/org/apache/lucene/search/MultiSearcher.java =================================================================== --- src/java/org/apache/lucene/search/MultiSearcher.java (revision 726211) +++ src/java/org/apache/lucene/search/MultiSearcher.java (working copy) @@ -96,7 +96,7 @@ throw new UnsupportedOperationException(); } - public void search(Weight weight, Filter filter, HitCollector results) { + public void search(Weight weight, Filter filter, DocCollector results) { throw new UnsupportedOperationException(); } @@ -252,18 +252,12 @@ // inherit javadoc - public void search(Weight weight, Filter filter, final HitCollector results) + public void search(Weight weight, Filter filter, final DocCollector results) throws IOException { for (int i = 0; i < searchables.length; i++) { - final int start = starts[i]; - - searchables[i].search(weight, filter, new HitCollector() { - public void collect(int doc, float score) { - results.collect(doc + start, score); - } - }); - + results.setDocBase(start); + searchables[i].search(weight, filter, results); } } Index: src/java/org/apache/lucene/search/Hits.java =================================================================== --- src/java/org/apache/lucene/search/Hits.java (revision 726211) +++ src/java/org/apache/lucene/search/Hits.java (working copy) @@ -30,7 +30,7 @@ * Caution: Iterate only over the hits needed. Iterating over all * hits is generally not desirable and may be the source of * performance issues. If you need to iterate over many or all hits, consider - * using the search method that takes a {@link HitCollector}. + * using the search method that takes a {@link DocCollector}. *

*

Note: Deleting matching documents concurrently with traversing * the hits, might, when deleting hits that were not yet retrieved, decrease @@ -203,7 +203,7 @@ * Caution: Iterate only over the hits needed. Iterating over all * hits is generally not desirable and may be the source of * performance issues. If you need to iterate over many or all hits, consider - * using a search method that takes a {@link HitCollector}. + * using a search method that takes a {@link DocCollector}. *

*/ public Iterator iterator() { Index: src/java/org/apache/lucene/search/QueryWrapperFilter.java =================================================================== --- src/java/org/apache/lucene/search/QueryWrapperFilter.java (revision 726211) +++ src/java/org/apache/lucene/search/QueryWrapperFilter.java (working copy) @@ -51,10 +51,14 @@ public BitSet bits(IndexReader reader) throws IOException { final BitSet bits = new BitSet(reader.maxDoc()); - new IndexSearcher(reader).search(query, new HitCollector() { + new IndexSearcher(reader).search(query, new DocCollector() { + private int base; public final void collect(int doc, float score) { - bits.set(doc); // set bit for hit + bits.set(doc + base); // set bit for hit } + public void setDocBase(int base) { + this.base = base; + } }); return bits; } Index: src/java/org/apache/lucene/search/TimeLimitedCollector.java =================================================================== --- src/java/org/apache/lucene/search/TimeLimitedCollector.java (revision 726211) +++ src/java/org/apache/lucene/search/TimeLimitedCollector.java (working copy) @@ -22,6 +22,8 @@ * take longer than the maximum allowed search time limit. After this * time is exceeded, the search thread is stopped by throwing a * TimeExceeded Exception.

+ * + * @deprecated use {@link TimeLimitedCollector} */ public class TimeLimitedCollector extends HitCollector { @@ -138,14 +140,16 @@ private final long t0; private final long timeout; - private final HitCollector hc; + private final DocCollector hc; + private int docBase; + /** * Create a TimeLimitedCollector wrapper over another HitCollector with a specified timeout. * @param hc the wrapped HitCollector * @param timeAllowed max time allowed for collecting hits after which {@link TimeExceededException} is thrown */ - public TimeLimitedCollector( final HitCollector hc, final long timeAllowed ) { + public TimeLimitedCollector( final DocCollector hc, final long timeAllowed ) { this.hc = hc; t0 = TIMER_THREAD.getMilliseconds(); this.timeout = t0 + timeAllowed; @@ -161,13 +165,13 @@ if( timeout < time) { if (greedy) { //System.out.println(this+" greedy: before failing, collecting doc: "+doc+" "+(time-t0)); - hc.collect( doc, score ); + hc.collect( doc + docBase, score ); } //System.out.println(this+" failing on: "+doc+" "+(time-t0)); throw new TimeExceededException( timeout-t0, time-t0, doc ); } //System.out.println(this+" collecting: "+doc+" "+(time-t0)); - hc.collect( doc, score ); + hc.collect( doc + docBase, score ); } /** @@ -216,4 +220,11 @@ public void setGreedy(boolean greedy) { this.greedy = greedy; } + + /* (non-Javadoc) + * @see org.apache.lucene.search.HitCollector#setDocBase(int) + */ + public void setDocBase(int base) { + this.docBase = base; + } } Index: src/java/org/apache/lucene/search/ParallelMultiSearcher.java =================================================================== --- src/java/org/apache/lucene/search/ParallelMultiSearcher.java (revision 726211) +++ src/java/org/apache/lucene/search/ParallelMultiSearcher.java (working copy) @@ -150,7 +150,7 @@ /** Lower-level search API. * - *

{@link HitCollector#collect(int,float)} is called for every matching + *

{@link DocCollector#collect(int,float)} is called for every matching * document. * *

Applications should only use this if they need all of the @@ -164,16 +164,20 @@ * * @todo parallelize this one too */ - public void search(Weight weight, Filter filter, final HitCollector results) + public void search(Weight weight, Filter filter, final DocCollector results) throws IOException { for (int i = 0; i < searchables.length; i++) { final int start = starts[i]; - searchables[i].search(weight, filter, new HitCollector() { + searchables[i].search(weight, filter, new DocCollector() { + private int base; public void collect(int doc, float score) { - results.collect(doc + start, score); + results.collect(doc + base + start, score); } + public void setDocBase(int base) { + this.base = base; + } }); } Index: src/java/org/apache/lucene/search/IndexSearcher.java =================================================================== --- src/java/org/apache/lucene/search/IndexSearcher.java (revision 726211) +++ src/java/org/apache/lucene/search/IndexSearcher.java (working copy) @@ -17,6 +17,8 @@ * limitations under the License. */ +import java.io.IOException; + import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldSelector; import org.apache.lucene.index.CorruptIndexException; @@ -24,8 +26,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.store.Directory; -import java.io.IOException; - /** Implements search over a single IndexReader. * *

Applications usually need only call the inherited {@link #search(Query)} @@ -38,6 +38,7 @@ public class IndexSearcher extends Searcher { IndexReader reader; private boolean closeReader; + private final int[] starts; /** Creates a searcher searching the index in the named directory. * @throws CorruptIndexException if the index is corrupt @@ -63,6 +64,13 @@ private IndexSearcher(IndexReader r, boolean closeReader) { reader = r; this.closeReader = closeReader; + IndexReader[] subReaders = r.getSequentialReaders(); + starts = new int[subReaders.length]; + int maxDoc = 0; + for (int i = 0; i < subReaders.length; i++) { + starts[i] = maxDoc; + maxDoc += subReaders[i].maxDoc(); // compute maxDocs + } } /** Return the {@link IndexReader} this searches. */ @@ -104,13 +112,9 @@ // inherit javadoc public TopDocs search(Weight weight, Filter filter, final int nDocs) throws IOException { - - if (nDocs <= 0) // null might be returned from hq.top() below. - throw new IllegalArgumentException("nDocs must be > 0"); - TopDocCollector collector = new TopDocCollector(nDocs); search(weight, filter, collector); - return collector.topDocs(); + return (TopDocs) collector.topDocs(); } // inherit javadoc @@ -118,15 +122,43 @@ Sort sort) throws IOException { - TopFieldDocCollector collector = - new TopFieldDocCollector(reader, sort, nDocs); + TopFieldValueDocCollector collector = new TopFieldValueDocCollector(sort, nDocs); search(weight, filter, collector); - return (TopFieldDocs)collector.topDocs(); + + return (TopFieldDocs) collector.topDocs(starts); } - + // inherit javadoc public void search(Weight weight, Filter filter, - final HitCollector results) throws IOException { + final DocCollector results) throws IOException { + IndexReader[] readers = reader.getSequentialReaders(); + if (readers.length > 1) { + // TODO: Remove in Lucene 3.0 + DocCollector collector = results; + try { + collector.setDocBase(starts[0]); + collector.setNextReader(readers[0]); + } catch(UnsupportedOperationException e) { + collector = new DocBaseCollector(results); + collector.setDocBase(starts[0]); + } + + doSearch (readers[0], weight, filter, collector); + + for (int i = 1; i < readers.length; i++) { // search each searcher + collector.setDocBase(starts[i]); + collector.setNextReader(readers[i]); + doSearch (readers[i], weight, filter, collector); + } + } else { + results.setNextReader(readers[0]); + results.setDocBase(0); + doSearch(reader, weight, filter, results); + } + } + + private void doSearch(IndexReader reader, Weight weight, Filter filter, + final DocCollector results) throws IOException { Scorer scorer = weight.scorer(reader); if (scorer == null) @@ -138,7 +170,7 @@ } DocIdSetIterator filterDocIdIterator = filter.getDocIdSet(reader).iterator(); // CHECKME: use ConjunctionScorer here? - + boolean more = filterDocIdIterator.next() && scorer.skipTo(filterDocIdIterator.doc()); while (more) { @@ -156,7 +188,7 @@ } } } - + public Query rewrite(Query original) throws IOException { Query query = original; for (Query rewrittenQuery = query.rewrite(reader); rewrittenQuery != query; @@ -169,4 +201,25 @@ public Explanation explain(Weight weight, int doc) throws IOException { return weight.explain(reader, doc); } + + private class DocBaseCollector extends DocCollector { + private DocCollector collector; + private int base; + + public DocBaseCollector(DocCollector collector) { + this.collector = collector; + } + + public void collect(int doc, float score) { + collector.collect(doc + base, score); + } + + public void setDocBase(int base) { + this.base = base; + } + + public boolean supportsDocBase() { + return true; + } + } } Index: src/java/org/apache/lucene/search/TermScorer.java =================================================================== --- src/java/org/apache/lucene/search/TermScorer.java (revision 726211) +++ src/java/org/apache/lucene/search/TermScorer.java (working copy) @@ -56,12 +56,12 @@ scoreCache[i] = getSimilarity().tf(i) * weightValue; } - public void score(HitCollector hc) throws IOException { + public void score(DocCollector hc) throws IOException { next(); score(hc, Integer.MAX_VALUE); } - protected boolean score(HitCollector c, int end) throws IOException { + protected boolean score(DocCollector c, int end) throws IOException { Similarity similarity = getSimilarity(); // cache sim in local float[] normDecoder = Similarity.getNormDecoder(); while (doc < end) { // for docs in window @@ -156,7 +156,7 @@ /** Returns an explanation of the score for a document. *
When this method is used, the {@link #next()} method - * and the {@link #score(HitCollector)} method should not be used. + * and the {@link #score(DocCollector)} method should not be used. * @param doc The document number for the explanation. */ public Explanation explain(int doc) throws IOException { Index: src/java/org/apache/lucene/index/MultiReader.java =================================================================== --- src/java/org/apache/lucene/index/MultiReader.java (revision 726211) +++ src/java/org/apache/lucene/index/MultiReader.java (working copy) @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -365,7 +364,11 @@ throw new UnsupportedOperationException("MultiReader does not support this method."); } - // for testing + public IndexReader[] getSequentialReaders() { + return subReaders; + } + + // for testing IndexReader[] getSubReaders() { return subReaders; } Index: src/java/org/apache/lucene/index/FilterIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/FilterIndexReader.java (revision 726211) +++ src/java/org/apache/lucene/index/FilterIndexReader.java (working copy) @@ -227,4 +227,8 @@ ensureOpen(); return in.isOptimized(); } + + public IndexReader[] getSequentialReaders() { + return in.getSequentialReaders(); + } } Index: src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- src/java/org/apache/lucene/index/IndexReader.java (revision 726211) +++ src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -1134,4 +1134,9 @@ public static Collection listCommits(Directory dir) throws IOException { return DirectoryIndexReader.listCommits(dir); } + + public IndexReader[] getSequentialReaders() { + return new IndexReader[] {this}; + } + } Index: src/java/org/apache/lucene/index/MultiSegmentReader.java =================================================================== --- src/java/org/apache/lucene/index/MultiSegmentReader.java (revision 726211) +++ src/java/org/apache/lucene/index/MultiSegmentReader.java (working copy) @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -432,6 +431,10 @@ return fieldSet; } + public IndexReader[] getSequentialReaders() { + return subReaders; + } + // for testing SegmentReader[] getSubReaders() { return subReaders; Index: contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java =================================================================== --- contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java (revision 726211) +++ contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java (working copy) @@ -16,9 +16,9 @@ package org.apache.lucene.store.instantiated; import junit.framework.TestCase; + +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.TopDocCollector; -import org.apache.lucene.search.HitCollector; import org.apache.lucene.search.TermQuery; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -56,11 +56,14 @@ } - public static class Collector extends HitCollector { + public static class Collector extends DocCollector { private int hits = 0; public void collect(int doc, float score) { hits++; } + public void setDocBase(int base) { + + } } } Index: contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java =================================================================== --- contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java (revision 726211) +++ contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java (working copy) @@ -25,11 +25,11 @@ import org.apache.lucene.index.Term; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.DefaultSimilarity; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.HitCollector; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.store.Directory; import org.apache.lucene.analysis.SimpleAnalyzer; @@ -126,10 +126,14 @@ float lastScore = 0.0f; // default similarity should put docs with shorter length first - searcher.search(new TermQuery(new Term("field", "word")), new HitCollector() { + searcher.search(new TermQuery(new Term("field", "word")), new DocCollector() { + private int base; public final void collect(int doc, float score) { - scores[doc] = score; + scores[doc + base] = score; } + public void setDocBase(int base) { + this.base = base; + } }); searcher.close(); @@ -146,10 +150,14 @@ // new norm (with default similarity) should put longer docs first searcher = new IndexSearcher(store); - searcher.search(new TermQuery(new Term("field", "word")), new HitCollector() { + searcher.search(new TermQuery(new Term("field", "word")), new DocCollector() { + private int base; public final void collect(int doc, float score) { - scores[doc] = score; + scores[doc + base] = score; } + public void setDocBase(int base) { + this.base = base; + } }); searcher.close(); @@ -183,10 +191,14 @@ float lastScore = 0.0f; // default similarity should return the same score for all documents for this query - searcher.search(new TermQuery(new Term("untokfield", "20061212")), new HitCollector() { + searcher.search(new TermQuery(new Term("untokfield", "20061212")), new DocCollector() { + private int base; public final void collect(int doc, float score) { - scores[doc] = score; + scores[doc + base] = score; } + public void setDocBase(int base) { + this.base = base; + } }); searcher.close(); Index: contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java =================================================================== --- contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java (revision 726211) +++ contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java (working copy) @@ -22,11 +22,11 @@ import org.apache.lucene.index.Term; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.DefaultSimilarity; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.HitCollector; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.store.Directory; import org.apache.lucene.analysis.SimpleAnalyzer; @@ -130,15 +130,17 @@ float lastScore = 0.0f; // default similarity should put docs with shorter length first - searcher = new IndexSearcher(store); - searcher.search - (new TermQuery(new Term("field", "word")), - new HitCollector() { - public final void collect(int doc, float score) { - scores[doc] = score; - } - }); - searcher.close(); + searcher = new IndexSearcher(store); + searcher.search(new TermQuery(new Term("field", "word")), new DocCollector() { + private int base; + public final void collect(int doc, float score) { + scores[doc + base] = score; + } + public void setDocBase(int base) { + this.base = base; + } + }); + searcher.close(); lastScore = Float.MAX_VALUE; for (int i = 0; i < NUM_DOCS; i++) { @@ -159,14 +161,16 @@ // new norm (with default similarity) should put longer docs first searcher = new IndexSearcher(store); - searcher.search - (new TermQuery(new Term("field", "word")), - new HitCollector() { - public final void collect(int doc, float score) { - scores[doc] = score; - } - }); - searcher.close(); + searcher.search(new TermQuery(new Term("field", "word")), new DocCollector() { + private int base; + public final void collect(int doc, float score) { + scores[doc + base] = score; + } + public void setDocBase(int base) { + this.base = base; + } + }); + searcher.close(); lastScore = 0.0f; for (int i = 0; i < NUM_DOCS; i++) { Index: contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java =================================================================== --- contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java (revision 726211) +++ contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java (working copy) @@ -45,7 +45,7 @@ import org.apache.lucene.index.IndexWriter; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; -import org.apache.lucene.search.HitCollector; +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Searcher; @@ -410,10 +410,11 @@ searcher = ((MemoryIndex) index).createSearcher(); final float[] scores = new float[1]; // inits to 0.0f - searcher.search(query, new HitCollector() { + searcher.search(query, new DocCollector() { public void collect(int doc, float score) { scores[0] = score; } + public void setDocBase(int base) {} }); float score = scores[0]; // Hits hits = searcher.search(query); Index: contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java =================================================================== --- contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (revision 726211) +++ contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (working copy) @@ -42,7 +42,7 @@ import org.apache.lucene.index.TermPositions; import org.apache.lucene.index.TermVectorMapper; import org.apache.lucene.index.FieldInvertState; -import org.apache.lucene.search.HitCollector; +import org.apache.lucene.search.DocCollector; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Searcher; @@ -422,10 +422,11 @@ Searcher searcher = createSearcher(); try { final float[] scores = new float[1]; // inits to 0.0f (no match) - searcher.search(query, new HitCollector() { + searcher.search(query, new DocCollector() { public void collect(int doc, float score) { scores[0] = score; } + public void setDocBase(int base) {} }); float score = scores[0]; return score;