diff --git a/CHANGES.txt b/CHANGES.txt index aa20080d384..afa610793cc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -53,6 +53,17 @@ Changes in backwards compatibility policy which was unlikely done, because there is no possibility to change Lucene's FieldCache implementation. (Grant Ingersoll, Uwe Schindler) + 3. LUCENE-1630: Deprecate Weight in favor of QueryWeight: added + matching methods to Searcher to take QueryWeight and deprecated + those taking Weight. If you have a Weight implementation, you can + turn it into a QueryWeight with QueryWeightWrapper (will be + removed in 3.0). All of the Weight-based methods were implemented + by calling the QueryWeight variants by wrapping the given Weight. + Going forward Searchable will be kept for convenience only and may + be changed between minor releases without any deprecation + process. It is not recommended to implement it, but rather extend + Searcher. (Shai Erera via Mike McCandless) + Changes in runtime behavior 1. LUCENE-1424: QueryParser now by default uses constant score query @@ -225,6 +236,24 @@ API Changes NumericRangeQuery and its new indexing format for numeric or date values. (Uwe Schindler) +23. LUCENE-1630: Deprecate Weight in favor of QueryWeight, which adds + a scorer(IndexReader, boolean /* scoreDocsInOrder */, boolean /* + topScorer */) method instead of scorer(IndexReader) (now + deprecated). The new method is used by IndexSearcher to mate + between Collector and Scorer orderness of doc IDs. Some Scorers + (like BooleanScorer) are much more efficient if out-of-order + documents scoring is allowed by a Collector. Collector must now + implement acceptsDocsOutOfOrder. If you write a Collector which + does not care about doc ID orderness, it is recommended that you + return true. QueryWeight has the scoresDocsOutOfOrder method, + which by default returns false. If you create a QueryWeight which + will score documents out of order if that's requested, you should + override that method to return true. Also deprecated + BooleanQuery's setAllowDocsOutOfOrder and getAllowDocsOutOfOrder + as they are not needed anymore. BooleanQuery will now score docs + out of order when used with a Collector that can accept docs out + of order. (Shai Erera via Mike McCandless) + Bug fixes 1. LUCENE-1415: MultiPhraseQuery has incorrect hashCode() and equals() diff --git a/contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java b/contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java index a4f248c5da3..023f9701be6 100644 --- a/contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java +++ b/contrib/miscellaneous/src/test/org/apache/lucene/index/TestFieldNormModifier.java @@ -146,6 +146,9 @@ public class TestFieldNormModifier extends TestCase { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); searcher.close(); @@ -174,6 +177,9 @@ public class TestFieldNormModifier extends TestCase { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); searcher.close(); @@ -219,6 +225,9 @@ public class TestFieldNormModifier extends TestCase { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); searcher.close(); diff --git a/contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java b/contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java index c2f74f11e22..a893b41d160 100644 --- a/contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java +++ b/contrib/miscellaneous/src/test/org/apache/lucene/misc/TestLengthNormModifier.java @@ -153,6 +153,9 @@ public class TestLengthNormModifier extends TestCase { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); searcher.close(); @@ -187,6 +190,9 @@ public class TestLengthNormModifier extends TestCase { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); searcher.close(); diff --git a/contrib/remote/src/java/org/apache/lucene/search/RemoteSearchable.java b/contrib/remote/src/java/org/apache/lucene/search/RemoteSearchable.java index 6251e69332c..b8365458bf9 100644 --- a/contrib/remote/src/java/org/apache/lucene/search/RemoteSearchable.java +++ b/contrib/remote/src/java/org/apache/lucene/search/RemoteSearchable.java @@ -48,11 +48,16 @@ public class RemoteSearchable /** @deprecated use {@link #search(Weight, Filter, Collector)} instead. */ public void search(Weight weight, Filter filter, HitCollector results) throws IOException { - local.search(weight, filter, results); + search(new QueryWeightWrapper(weight), filter, new HitCollectorWrapper(results)); } public void search(Weight weight, Filter filter, Collector results) throws IOException { + search(new QueryWeightWrapper(weight), filter, results); + } + + public void search(QueryWeight weight, Filter filter, Collector results) + throws IOException { local.search(weight, filter, results); } @@ -74,11 +79,19 @@ public class RemoteSearchable } public TopDocs search(Weight weight, Filter filter, int n) throws IOException { + return search(new QueryWeightWrapper(weight), filter, n); + } + + public TopDocs search(QueryWeight weight, Filter filter, int n) throws IOException { return local.search(weight, filter, n); } - - public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort) + public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) + throws IOException { + return search(new QueryWeightWrapper(weight), filter, n, sort); + } + + public TopFieldDocs search(QueryWeight weight, Filter filter, int n, Sort sort) throws IOException { return local.search (weight, filter, n, sort); } @@ -96,6 +109,10 @@ public class RemoteSearchable } public Explanation explain(Weight weight, int doc) throws IOException { + return explain(new QueryWeightWrapper(weight), doc); + } + + public Explanation explain(QueryWeight weight, int doc) throws IOException { return local.explain(weight, doc); } diff --git a/src/java/org/apache/lucene/index/DocumentsWriter.java b/src/java/org/apache/lucene/index/DocumentsWriter.java index 2c1492e3cd7..b30edae9528 100644 --- a/src/java/org/apache/lucene/index/DocumentsWriter.java +++ b/src/java/org/apache/lucene/index/DocumentsWriter.java @@ -17,27 +17,27 @@ package org.apache.lucene.index; * limitations under the License. */ -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.document.Document; -import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Weight; -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.AlreadyClosedException; -import org.apache.lucene.util.ArrayUtil; - import java.io.IOException; import java.io.PrintStream; +import java.text.NumberFormat; +import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; -import java.util.List; import java.util.HashMap; import java.util.HashSet; -import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Map.Entry; -import java.text.NumberFormat; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.QueryWeight; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.store.AlreadyClosedException; +import org.apache.lucene.store.Directory; +import org.apache.lucene.util.ArrayUtil; /** * This class accepts multiple added documents and directly @@ -172,7 +172,7 @@ final class DocumentsWriter { void setNext(DocWriter next) { this.next = next; } - }; + } /** * The IndexingChain must define the {@link #getChain(DocumentsWriter)} method @@ -303,7 +303,7 @@ final class DocumentsWriter { synchronized void setAllowMinus1Position() { for(int i=0;i= limit) @@ -1144,7 +1144,7 @@ final class DocumentsWriter { /* Initial chunks size of the shared byte[] blocks used to store postings data */ final static int BYTE_BLOCK_SHIFT = 15; - final static int BYTE_BLOCK_SIZE = (int) (1 << BYTE_BLOCK_SHIFT); + final static int BYTE_BLOCK_SIZE = 1 << BYTE_BLOCK_SHIFT; final static int BYTE_BLOCK_MASK = BYTE_BLOCK_SIZE - 1; final static int BYTE_BLOCK_NOT_MASK = ~BYTE_BLOCK_MASK; @@ -1187,7 +1187,7 @@ final class DocumentsWriter { /* Initial chunks size of the shared int[] blocks used to store postings data */ final static int INT_BLOCK_SHIFT = 13; - final static int INT_BLOCK_SIZE = (int) (1 << INT_BLOCK_SHIFT); + final static int INT_BLOCK_SIZE = 1 << INT_BLOCK_SHIFT; final static int INT_BLOCK_MASK = INT_BLOCK_SIZE - 1; private ArrayList freeIntBlocks = new ArrayList(); @@ -1234,7 +1234,7 @@ final class DocumentsWriter { /* Initial chunk size of the shared char[] blocks used to store term text */ final static int CHAR_BLOCK_SHIFT = 14; - final static int CHAR_BLOCK_SIZE = (int) (1 << CHAR_BLOCK_SHIFT); + final static int CHAR_BLOCK_SIZE = 1 << CHAR_BLOCK_SHIFT; final static int CHAR_BLOCK_MASK = CHAR_BLOCK_SIZE - 1; final static int MAX_TERM_LENGTH = CHAR_BLOCK_SIZE-1; @@ -1283,7 +1283,7 @@ final class DocumentsWriter { void balanceRAM() { // We flush when we've used our target usage - final long flushTrigger = (long) ramBufferSize; + final long flushTrigger = ramBufferSize; if (numBytesAlloc > freeTrigger) { diff --git a/src/java/org/apache/lucene/search/BooleanQuery.java b/src/java/org/apache/lucene/search/BooleanQuery.java index 0b37084dc5d..932db8cd735 100644 --- a/src/java/org/apache/lucene/search/BooleanQuery.java +++ b/src/java/org/apache/lucene/search/BooleanQuery.java @@ -30,7 +30,6 @@ import java.util.*; */ public class BooleanQuery extends Query { - private static int maxClauseCount = 1024; /** Thrown when an attempt is made to add more than {@link @@ -173,7 +172,7 @@ public class BooleanQuery extends Query { /** Returns the list of clauses in this query. */ public List clauses() { return clauses; } - private class BooleanWeight implements Weight { + private class BooleanWeight extends QueryWeight { protected Similarity similarity; protected ArrayList weights; @@ -183,7 +182,7 @@ public class BooleanQuery extends Query { weights = new ArrayList(clauses.size()); for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.get(i); - weights.add(c.getQuery().createWeight(searcher)); + weights.add(c.getQuery().createQueryWeight(searcher)); } } @@ -194,7 +193,7 @@ public class BooleanQuery extends Query { float sum = 0.0f; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.get(i); - Weight w = (Weight)weights.get(i); + QueryWeight w = (QueryWeight)weights.get(i); // call sumOfSquaredWeights for all clauses in case of side effects float s = w.sumOfSquaredWeights(); // sum sub weights if (!c.isProhibited()) @@ -210,39 +209,13 @@ public class BooleanQuery extends Query { public void normalize(float norm) { norm *= getBoost(); // incorporate boost - for (int i = 0 ; i < weights.size(); i++) { - Weight w = (Weight)weights.get(i); + for (Iterator iter = weights.iterator(); iter.hasNext();) { + QueryWeight w = (QueryWeight) iter.next(); // normalize all clauses, (even if prohibited in case of side affects) w.normalize(norm); } } - /** - * @return Returns BooleanScorer2 that uses and provides advance(), and - * scores documents in document number order. - */ - public Scorer scorer(IndexReader reader) throws IOException { - // TODO (3.0): instantiate either BS or BS2, according to - // allowDocsOutOfOrder (basically, try to inline BS2.score(Collector)'s - // logic. - - BooleanScorer2 result = new BooleanScorer2(similarity, - minNrShouldMatch, - allowDocsOutOfOrder); - - for (int i = 0 ; i < weights.size(); i++) { - BooleanClause c = (BooleanClause)clauses.get(i); - Weight w = (Weight)weights.get(i); - Scorer subScorer = w.scorer(reader); - if (subScorer != null) - result.add(subScorer, c.isRequired(), c.isProhibited()); - else if (c.isRequired()) - return null; - } - - return result; - } - public Explanation explain(IndexReader reader, int doc) throws IOException { final int minShouldMatch = @@ -256,7 +229,7 @@ public class BooleanQuery extends Query { int shouldMatchCount = 0; for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.get(i); - Weight w = (Weight)weights.get(i); + QueryWeight w = (QueryWeight)weights.get(i); Explanation e = w.explain(reader, doc); if (!c.isProhibited()) maxCoord++; if (e.isMatch()) { @@ -310,41 +283,101 @@ public class BooleanQuery extends Query { return result; } } + + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) + throws IOException { + List required = new ArrayList(); + List prohibited = new ArrayList(); + List optional = new ArrayList(); + for (Iterator wIter = weights.iterator(), cIter = clauses.iterator(); wIter.hasNext();) { + QueryWeight w = (QueryWeight) wIter.next(); + BooleanClause c = (BooleanClause) cIter.next(); + Scorer subScorer = w.scorer(reader, true, false); + if (subScorer == null) { + return null; + } else if (c.isRequired()) { + required.add(subScorer); + } else if (c.isProhibited()) { + prohibited.add(subScorer); + } else { + optional.add(subScorer); + } + } + + // Check if we can return a BooleanScorer + scoreDocsInOrder |= !allowDocsOutOfOrder; // until it is removed, factor in the static setting. + if (!scoreDocsInOrder && topScorer && required.size() == 0 && prohibited.size() < 32) { + return new BooleanScorer(similarity, minNrShouldMatch, optional, prohibited); + } + + // Return a BooleanScorer2 + return new BooleanScorer2(similarity, minNrShouldMatch, required, prohibited, optional); + } + + public boolean scoresDocsOutOfOrder() { + int numProhibited = 0; + for (Iterator cIter = clauses.iterator(); cIter.hasNext();) { + BooleanClause c = (BooleanClause) cIter.next(); + if (c.isRequired()) { + return false; // BS2 (in-order) will be used by scorer() + } else if (c.isProhibited()) { + ++numProhibited; + } + } + + if (numProhibited > 32) { // cannot use BS + return false; + } + + // scorer() will return an out-of-order scorer if requested. + return true; + } + } - /** Whether hit docs may be collected out of docid order. */ - private static boolean allowDocsOutOfOrder = false; + /** + * Whether hit docs may be collected out of docid order. + * + * @deprecated this will not be needed anymore, as + * {@link QueryWeight#scoresDocsOutOfOrder()} is used. + */ + private static boolean allowDocsOutOfOrder = true; /** - * Expert: Indicates whether hit docs may be collected out of docid - * order. - * + * Expert: Indicates whether hit docs may be collected out of docid order. + * *

* Background: although the contract of the Scorer class requires that * documents be iterated in order of doc id, this was not true in early - * versions of Lucene. Many pieces of functionality in the current - * Lucene code base have undefined behavior if this contract is not - * upheld, but in some specific simple cases may be faster. (For - * example: disjunction queries with less than 32 prohibited clauses; - * This setting has no effect for other queries.) + * versions of Lucene. Many pieces of functionality in the current Lucene code + * base have undefined behavior if this contract is not upheld, but in some + * specific simple cases may be faster. (For example: disjunction queries with + * less than 32 prohibited clauses; This setting has no effect for other + * queries.) *

- * + * *

- * Specifics: By setting this option to true, docid N might be scored - * for a single segment before docid N-1. Across multiple segments, - * docs may be scored out of order regardless of this setting - it only - * applies to scoring a single segment. + * Specifics: By setting this option to true, docid N might be scored for a + * single segment before docid N-1. Across multiple segments, docs may be + * scored out of order regardless of this setting - it only applies to scoring + * a single segment. * * Being static, this setting is system wide. *

+ * + * @deprecated this is not needed anymore, as + * {@link QueryWeight#scoresDocsOutOfOrder()} is used. */ public static void setAllowDocsOutOfOrder(boolean allow) { allowDocsOutOfOrder = allow; - } - + } + /** * Whether hit docs may be collected out of docid order. + * * @see #setAllowDocsOutOfOrder(boolean) + * @deprecated this is not needed anymore, as + * {@link QueryWeight#scoresDocsOutOfOrder()} is used. */ public static boolean getAllowDocsOutOfOrder() { return allowDocsOutOfOrder; @@ -364,7 +397,7 @@ public class BooleanQuery extends Query { return getAllowDocsOutOfOrder(); } - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new BooleanWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/BooleanScorer.java b/src/java/org/apache/lucene/search/BooleanScorer.java index f0ca6279dea..7e75d21fd18 100644 --- a/src/java/org/apache/lucene/search/BooleanScorer.java +++ b/src/java/org/apache/lucene/search/BooleanScorer.java @@ -92,9 +92,15 @@ final class BooleanScorer extends Scorer { public void setNextReader(IndexReader reader, int docBase) { // not needed by this implementation } + public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } // An internal class which is used in score(Collector, int) for setting the diff --git a/src/java/org/apache/lucene/search/BooleanScorer2.java b/src/java/org/apache/lucene/search/BooleanScorer2.java index 0227ecfd22d..45a90fca6f5 100644 --- a/src/java/org/apache/lucene/search/BooleanScorer2.java +++ b/src/java/org/apache/lucene/search/BooleanScorer2.java @@ -30,9 +30,10 @@ import java.util.List; *
Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer. */ class BooleanScorer2 extends Scorer { - private ArrayList requiredScorers = new ArrayList(); - private ArrayList optionalScorers = new ArrayList(); - private ArrayList prohibitedScorers = new ArrayList(); + + private final List requiredScorers; + private final List optionalScorers; + private final List prohibitedScorers; private class Coordinator { float[] coordFactors = null; @@ -54,90 +55,52 @@ class BooleanScorer2 extends Scorer { /** The scorer to which all scoring will be delegated, * except for computing and using the coordination factor. */ - private Scorer countingSumScorer = null; + private final Scorer countingSumScorer; /** The number of optionalScorers that need to match (if there are any) */ private final int minNrShouldMatch; - /** Whether it is allowed to return documents out of order. - * This can accelerate the scoring of disjunction queries. - */ - private boolean allowDocsOutOfOrder; - private int doc = -1; - /** Create a BooleanScorer2. - * @param similarity The similarity to be used. - * @param minNrShouldMatch The minimum number of optional added scorers - * that should match during the search. - * In case no required scorers are added, - * at least one of the optional scorers will have to - * match during the search. - * @param allowDocsOutOfOrder Whether it is allowed to return documents out of order. - * This can accelerate the scoring of disjunction queries. + /** + * Creates a {@link Scorer} with the given similarity and lists of required, + * prohibited and optional scorers. In no required scorers are added, at least + * one of the optional scorers will have to match during the search. + * + * @param similarity + * The similarity to be used. + * @param minNrShouldMatch + * The minimum number of optional added scorers that should match + * during the search. In case no required scorers are added, at least + * one of the optional scorers will have to match during the search. + * @param required + * the list of required scorers. + * @param prohibited + * the list of prohibited scorers. + * @param optional + * the list of optional scorers. */ - public BooleanScorer2(Similarity similarity, int minNrShouldMatch, boolean allowDocsOutOfOrder) throws IOException { + public BooleanScorer2(Similarity similarity, int minNrShouldMatch, + List required, List prohibited, List optional) throws IOException { super(similarity); if (minNrShouldMatch < 0) { throw new IllegalArgumentException("Minimum number of optional scorers should not be negative"); } coordinator = new Coordinator(); this.minNrShouldMatch = minNrShouldMatch; - this.allowDocsOutOfOrder = allowDocsOutOfOrder; - } - /** Create a BooleanScorer2. - * In no required scorers are added, - * at least one of the optional scorers will have to match during the search. - * @param similarity The similarity to be used. - * @param minNrShouldMatch The minimum number of optional added scorers - * that should match during the search. - * In case no required scorers are added, - * at least one of the optional scorers will have to - * match during the search. - */ - public BooleanScorer2(Similarity similarity, int minNrShouldMatch) throws IOException { - this(similarity, minNrShouldMatch, false); - } - - /** Create a BooleanScorer2. - * In no required scorers are added, - * at least one of the optional scorers will have to match during the search. - * @param similarity The similarity to be used. - */ - public BooleanScorer2(Similarity similarity) throws IOException { - this(similarity, 0, false); - } + optionalScorers = optional; + coordinator.maxCoord += optional.size(); - public void add(final Scorer scorer, boolean required, boolean prohibited) throws IOException { - if (!prohibited) { - coordinator.maxCoord++; - } - - if (required) { - if (prohibited) { - throw new IllegalArgumentException("scorer cannot be required and prohibited"); - } - requiredScorers.add(scorer); - } else if (prohibited) { - prohibitedScorers.add(scorer); - } else { - optionalScorers.add(scorer); - } - } - - /** Initialize the match counting scorer that sums all the - * scores.

- * When "counting" is used in a name it means counting the number - * of matching scorers.
- * When "sum" is used in a name it means score value summing - * over the matching scorers - */ - private void initCountingSumScorer() throws IOException { + requiredScorers = required; + coordinator.maxCoord += required.size(); + + prohibitedScorers = prohibited; + coordinator.init(); countingSumScorer = makeCountingSumScorer(); } - + /** Count a scorer as a single match. */ private class SingleMatchScorer extends Scorer { private Scorer scorer; @@ -333,19 +296,10 @@ class BooleanScorer2 extends Scorer { *
When this method is used the {@link #explain(int)} method should not be used. */ public void score(Collector collector) throws IOException { - if (allowDocsOutOfOrder && requiredScorers.size() == 0 - && prohibitedScorers.size() < 32) { - new BooleanScorer(getSimilarity(), minNrShouldMatch, optionalScorers, - prohibitedScorers).score(collector); - } else { - if (countingSumScorer == null) { - initCountingSumScorer(); - } - collector.setScorer(this); - int doc; - while ((doc = countingSumScorer.nextDoc()) != NO_MORE_DOCS) { - collector.collect(doc); - } + collector.setScorer(this); + int doc; + while ((doc = countingSumScorer.nextDoc()) != NO_MORE_DOCS) { + collector.collect(doc); } } @@ -386,9 +340,6 @@ class BooleanScorer2 extends Scorer { } public int nextDoc() throws IOException { - if (countingSumScorer == null) { - initCountingSumScorer(); - } return doc = countingSumScorer.nextDoc(); } @@ -404,9 +355,6 @@ class BooleanScorer2 extends Scorer { } public int advance(int target) throws IOException { - if (countingSumScorer == null) { - initCountingSumScorer(); - } return doc = countingSumScorer.advance(target); } diff --git a/src/java/org/apache/lucene/search/Collector.java b/src/java/org/apache/lucene/search/Collector.java index c6089f7cd2a..9d6782ee632 100644 --- a/src/java/org/apache/lucene/search/Collector.java +++ b/src/java/org/apache/lucene/search/Collector.java @@ -121,6 +121,8 @@ import org.apache.lucene.index.IndexReader; * *

NOTE: This API is experimental and might change * in incompatible ways in the next release.

+ * + * @since 2.9 */ public abstract class Collector { @@ -156,5 +158,17 @@ public abstract class Collector { * @param docBase */ public abstract void setNextReader(IndexReader reader, int docBase) throws IOException; + + /** + * Returns true iff this {@link Collector} can accept documents given to + * {@link #collect(int)} out of order. + *

+ * NOTE: some collectors can work in either mode, with a more efficient + * implementation for in-order docs collection. If your collector can work in + * either mode, it is recommended that you create two variants of it, since + * some queries work much faster if out-of-order collection is supported by a + * {@link Collector}. + */ + public abstract boolean acceptsDocsOutOfOrder(); } diff --git a/src/java/org/apache/lucene/search/ConstantScoreQuery.java b/src/java/org/apache/lucene/search/ConstantScoreQuery.java index 90bf51c2167..01f5856b49a 100644 --- a/src/java/org/apache/lucene/search/ConstantScoreQuery.java +++ b/src/java/org/apache/lucene/search/ConstantScoreQuery.java @@ -50,11 +50,11 @@ public class ConstantScoreQuery extends Query { // but may not be OK for highlighting } - protected class ConstantWeight implements Weight { + protected class ConstantWeight extends QueryWeight { private Similarity similarity; private float queryNorm; private float queryWeight; - + public ConstantWeight(Searcher searcher) { this.similarity = getSimilarity(searcher); } @@ -77,13 +77,13 @@ public class ConstantScoreQuery extends Query { queryWeight *= this.queryNorm; } - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { return new ConstantScorer(similarity, reader, this); } public Explanation explain(IndexReader reader, int doc) throws IOException { - ConstantScorer cs = (ConstantScorer)scorer(reader); + ConstantScorer cs = (ConstantScorer) scorer(reader, true, false); boolean exists = cs.docIdSetIterator.advance(doc) == doc; ComplexExplanation result = new ComplexExplanation(); @@ -110,7 +110,7 @@ public class ConstantScoreQuery extends Query { final float theScore; int doc = -1; - public ConstantScorer(Similarity similarity, IndexReader reader, Weight w) throws IOException { + public ConstantScorer(Similarity similarity, IndexReader reader, QueryWeight w) throws IOException { super(similarity); theScore = w.getValue(); docIdSetIterator = filter.getDocIdSet(reader).iterator(); @@ -152,7 +152,7 @@ public class ConstantScoreQuery extends Query { } } - protected Weight createWeight(Searcher searcher) { + public QueryWeight createQueryWeight(Searcher searcher) { return new ConstantScoreQuery.ConstantWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java b/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java index 4aa229940b9..a2edd224861 100644 --- a/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java +++ b/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java @@ -86,7 +86,7 @@ public class DisjunctionMaxQuery extends Query { } /* The Weight for DisjunctionMaxQuery's, used to normalize, score and explain these queries */ - private class DisjunctionMaxWeight implements Weight { + private class DisjunctionMaxWeight extends QueryWeight { private Similarity similarity; // The similarity which we are associated. private ArrayList weights = new ArrayList(); // The Weight's for our subqueries, in 1-1 correspondence with disjuncts @@ -94,8 +94,9 @@ public class DisjunctionMaxQuery extends Query { /* Construct the Weight for this Query searched by searcher. Recursively construct subquery weights. */ public DisjunctionMaxWeight(Searcher searcher) throws IOException { this.similarity = searcher.getSimilarity(); - for (int i = 0; i < disjuncts.size(); i++) - weights.add(((Query) disjuncts.get(i)).createWeight(searcher)); + for (Iterator iter = disjuncts.iterator(); iter.hasNext();) { + weights.add(((Query) iter.next()).createQueryWeight(searcher)); + } } /* Return our associated DisjunctionMaxQuery */ @@ -107,28 +108,32 @@ public class DisjunctionMaxQuery extends Query { /* Compute the sub of squared weights of us applied to our subqueries. Used for normalization. */ public float sumOfSquaredWeights() throws IOException { float max = 0.0f, sum = 0.0f; - for (int i = 0; i < weights.size(); i++) { - float sub = ((Weight) weights.get(i)).sumOfSquaredWeights(); + for (Iterator iter = weights.iterator(); iter.hasNext();) { + float sub = ((QueryWeight) iter.next()).sumOfSquaredWeights(); sum += sub; max = Math.max(max, sub); + } - return (((sum - max) * tieBreakerMultiplier * tieBreakerMultiplier) + max) * getBoost() * getBoost(); + float boost = getBoost(); + return (((sum - max) * tieBreakerMultiplier * tieBreakerMultiplier) + max) * boost * boost; } /* Apply the computed normalization factor to our subqueries */ public void normalize(float norm) { norm *= getBoost(); // Incorporate our boost - for (int i = 0 ; i < weights.size(); i++) - ((Weight) weights.get(i)).normalize(norm); + for (Iterator iter = weights.iterator(); iter.hasNext();) { + ((QueryWeight) iter.next()).normalize(norm); + } } /* Create the scorer used to score our associated DisjunctionMaxQuery */ - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, + boolean topScorer) throws IOException { Scorer[] scorers = new Scorer[weights.size()]; int idx = 0; for (Iterator iter = weights.iterator(); iter.hasNext();) { - Weight w = (Weight) iter.next(); - Scorer subScorer = w.scorer(reader); + QueryWeight w = (QueryWeight) iter.next(); + Scorer subScorer = w.scorer(reader, true, false); if (subScorer == null) { return null; } else if (subScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { @@ -142,12 +147,12 @@ public class DisjunctionMaxQuery extends Query { /* Explain the score we computed for doc */ public Explanation explain(IndexReader reader, int doc) throws IOException { - if ( disjuncts.size() == 1) return ((Weight) weights.get(0)).explain(reader,doc); + if (disjuncts.size() == 1) return ((QueryWeight) weights.get(0)).explain(reader,doc); ComplexExplanation result = new ComplexExplanation(); float max = 0.0f, sum = 0.0f; result.setDescription(tieBreakerMultiplier == 0.0f ? "max of:" : "max plus " + tieBreakerMultiplier + " times others of:"); - for (int i = 0 ; i < weights.size(); i++) { - Explanation e = ((Weight) weights.get(i)).explain(reader, doc); + for (Iterator iter = weights.iterator(); iter.hasNext();) { + Explanation e = ((QueryWeight) iter.next()).explain(reader, doc); if (e.isMatch()) { result.setMatch(Boolean.TRUE); result.addDetail(e); @@ -155,14 +160,14 @@ public class DisjunctionMaxQuery extends Query { max = Math.max(max, e.getValue()); } } - result.setValue(max + (sum - max)*tieBreakerMultiplier); + result.setValue(max + (sum - max) * tieBreakerMultiplier); return result; } - + } // end of DisjunctionMaxWeight inner class - /* Create the Weight used to score us */ - protected Weight createWeight(Searcher searcher) throws IOException { + /* Create the QueryWeight used to score us */ + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new DisjunctionMaxWeight(searcher); } @@ -170,7 +175,8 @@ public class DisjunctionMaxQuery extends Query { * @param reader the IndexReader we query * @return an optimized copy of us (which may not be a copy if there is nothing to optimize) */ public Query rewrite(IndexReader reader) throws IOException { - if (disjuncts.size() == 1) { + int numDisjunctions = disjuncts.size(); + if (numDisjunctions == 1) { Query singleton = (Query) disjuncts.get(0); Query result = singleton.rewrite(reader); if (getBoost() != 1.0f) { @@ -180,7 +186,7 @@ public class DisjunctionMaxQuery extends Query { return result; } DisjunctionMaxQuery clone = null; - for (int i = 0 ; i < disjuncts.size(); i++) { + for (int i = 0 ; i < numDisjunctions; i++) { Query clause = (Query) disjuncts.get(i); Query rewrite = clause.rewrite(reader); if (rewrite != clause) { @@ -200,15 +206,13 @@ public class DisjunctionMaxQuery extends Query { return clone; } - // inherit javadoc public void extractTerms(Set terms) { - for (int i = 0; i < disjuncts.size(); i++) { - ((Query)disjuncts.get(i)).extractTerms(terms); - } + for (Iterator iter = disjuncts.iterator(); iter.hasNext();) { + ((Query) iter.next()).extractTerms(terms); + } } - /** Prettyprint us. * @param field the field to which we are applied * @return a string that shows what we do, of the form "(disjunct1 | disjunct2 | ... | disjunctn)^boost" @@ -216,7 +220,8 @@ public class DisjunctionMaxQuery extends Query { public String toString(String field) { StringBuffer buffer = new StringBuffer(); buffer.append("("); - for (int i = 0 ; i < disjuncts.size(); i++) { + int numDisjunctions = disjuncts.size(); + for (int i = 0 ; i < numDisjunctions; i++) { Query subquery = (Query) disjuncts.get(i); if (subquery instanceof BooleanQuery) { // wrap sub-bools in parens buffer.append("("); @@ -224,7 +229,7 @@ public class DisjunctionMaxQuery extends Query { buffer.append(")"); } else buffer.append(subquery.toString(field)); - if (i != disjuncts.size()-1) buffer.append(" | "); + if (i != numDisjunctions-1) buffer.append(" | "); } buffer.append(")"); if (tieBreakerMultiplier != 0.0f) { diff --git a/src/java/org/apache/lucene/search/ExactPhraseScorer.java b/src/java/org/apache/lucene/search/ExactPhraseScorer.java index 6603a7c787e..692fd3284b8 100644 --- a/src/java/org/apache/lucene/search/ExactPhraseScorer.java +++ b/src/java/org/apache/lucene/search/ExactPhraseScorer.java @@ -22,8 +22,8 @@ import org.apache.lucene.index.*; final class ExactPhraseScorer extends PhraseScorer { - ExactPhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, Similarity similarity, - byte[] norms) { + ExactPhraseScorer(QueryWeight weight, TermPositions[] tps, int[] offsets, + Similarity similarity, byte[] norms) { super(weight, tps, offsets, similarity, norms); } @@ -43,13 +43,13 @@ final class ExactPhraseScorer extends PhraseScorer { while (first.position < last.position) { // scan forward in first do { if (!first.nextPosition()) - return (float)freq; + return freq; } while (first.position < last.position); firstToLast(); } freq++; // all equal: a match } while (last.nextPosition()); - return (float)freq; + return freq; } } diff --git a/src/java/org/apache/lucene/search/FilteredQuery.java b/src/java/org/apache/lucene/search/FilteredQuery.java index 9a11ee126a8..68869b1b0da 100644 --- a/src/java/org/apache/lucene/search/FilteredQuery.java +++ b/src/java/org/apache/lucene/search/FilteredQuery.java @@ -54,16 +54,14 @@ extends Query { this.filter = filter; } - - /** * Returns a Weight that applies the filter to the enclosed query's Weight. * This is accomplished by overriding the Scorer returned by the Weight. */ - protected Weight createWeight (final Searcher searcher) throws IOException { - final Weight weight = query.createWeight (searcher); + public QueryWeight createQueryWeight(final Searcher searcher) throws IOException { + final QueryWeight weight = query.createQueryWeight (searcher); final Similarity similarity = query.getSimilarity(searcher); - return new Weight() { + return new QueryWeight() { private float value; // pass these methods through to enclosed query's weight @@ -99,8 +97,9 @@ extends Query { public Query getQuery() { return FilteredQuery.this; } // return a filtering scorer - public Scorer scorer (IndexReader indexReader) throws IOException { - final Scorer scorer = weight.scorer(indexReader); + public Scorer scorer(IndexReader indexReader, boolean scoreDocsInOrder, boolean topScorer) + throws IOException { + final Scorer scorer = weight.scorer(indexReader, scoreDocsInOrder, false); final DocIdSetIterator docIdSetIterator = filter.getDocIdSet(indexReader).iterator(); return new Scorer(similarity) { diff --git a/src/java/org/apache/lucene/search/HitCollectorWrapper.java b/src/java/org/apache/lucene/search/HitCollectorWrapper.java index 8e383446f57..e4127f19358 100644 --- a/src/java/org/apache/lucene/search/HitCollectorWrapper.java +++ b/src/java/org/apache/lucene/search/HitCollectorWrapper.java @@ -25,7 +25,9 @@ import org.apache.lucene.index.IndexReader; * Wrapper for ({@link HitCollector}) implementations, which * simply re-bases the incoming docID before calling {@link * HitCollector#collect}. - * @deprecated this class will be removed when {@link HitCollector} is removed. + * @deprecated this class will be removed when {@link + * HitCollector} is removed. Please migrate custom + * HitCollectors to the new {@link Collector} class. */ public class HitCollectorWrapper extends Collector { private HitCollector collector; @@ -47,4 +49,9 @@ public class HitCollectorWrapper extends Collector { public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; } + + public boolean acceptsDocsOutOfOrder() { + return false; + } + } diff --git a/src/java/org/apache/lucene/search/Hits.java b/src/java/org/apache/lucene/search/Hits.java index 1e037458d7a..73c2f31412e 100644 --- a/src/java/org/apache/lucene/search/Hits.java +++ b/src/java/org/apache/lucene/search/Hits.java @@ -19,8 +19,8 @@ package org.apache.lucene.search; import java.io.IOException; import java.util.ConcurrentModificationException; -import java.util.Vector; import java.util.Iterator; +import java.util.Vector; import org.apache.lucene.document.Document; import org.apache.lucene.index.CorruptIndexException; @@ -53,7 +53,7 @@ import org.apache.lucene.index.CorruptIndexException; * */ public final class Hits { - private Weight weight; + private QueryWeight weight; private Searcher searcher; private Filter filter = null; private Sort sort = null; @@ -73,7 +73,7 @@ public final class Hits { boolean debugCheckedForDeletions = false; // for test purposes. Hits(Searcher s, Query q, Filter f) throws IOException { - weight = q.weight(s); + weight = q.queryWeight(s); searcher = s; filter = f; nDeletions = countDeletions(s); @@ -82,7 +82,7 @@ public final class Hits { } Hits(Searcher s, Query q, Filter f, Sort o) throws IOException { - weight = q.weight(s); + weight = q.queryWeight(s); searcher = s; filter = f; sort = o; diff --git a/src/java/org/apache/lucene/search/IndexSearcher.java b/src/java/org/apache/lucene/search/IndexSearcher.java index 56f0351ff84..ace8989d7d7 100644 --- a/src/java/org/apache/lucene/search/IndexSearcher.java +++ b/src/java/org/apache/lucene/search/IndexSearcher.java @@ -161,38 +161,33 @@ public class IndexSearcher extends Searcher { } // inherit javadoc - public TopDocs search(Weight weight, Filter filter, final int nDocs) - throws IOException { + public TopDocs search(QueryWeight weight, Filter filter, final int nDocs) throws IOException { - if (nDocs <= 0) // null might be returned from hq.top() below. + if (nDocs <= 0) { throw new IllegalArgumentException("nDocs must be > 0"); + } - // TODO: The following should be changed to first obtain a Scorer and then ask it - // if it's going to return in-order or out-of-order docs, and create TSDC - // accordingly. - TopScoreDocCollector collector = TopScoreDocCollector.create(nDocs, false); + TopScoreDocCollector collector = TopScoreDocCollector.create(nDocs, !weight.scoresDocsOutOfOrder()); search(weight, filter, collector); return collector.topDocs(); } - // inherit javadoc - public TopFieldDocs search(Weight weight, Filter filter, final int nDocs, - Sort sort) - throws IOException { + public TopFieldDocs search(QueryWeight weight, Filter filter, + final int nDocs, Sort sort) throws IOException { return search(weight, filter, nDocs, sort, true); } /** - * Just like {@link #search(Weight, Filter, int, Sort)}, but you choose + * Just like {@link #search(QueryWeight, Filter, int, Sort)}, but you choose * whether or not the fields in the returned {@link FieldDoc} instances should * be set by specifying fillFields.
* NOTE: currently, this method tracks document scores and sets them in * the returned {@link FieldDoc}, however in 3.0 it will move to not track * document scores. If document scores tracking is still needed, you can use - * {@link #search(Weight, Filter, Collector)} and pass in a + * {@link #search(QueryWeight, Filter, Collector)} and pass in a * {@link TopFieldCollector} instance. */ - public TopFieldDocs search(Weight weight, Filter filter, final int nDocs, + public TopFieldDocs search(QueryWeight weight, Filter filter, final int nDocs, Sort sort, boolean fillFields) throws IOException { @@ -222,50 +217,50 @@ public class IndexSearcher extends Searcher { TopDocCollector collector = new TopFieldDocCollector(reader, sort, nDocs); HitCollectorWrapper hcw = new HitCollectorWrapper(collector); hcw.setNextReader(reader, 0); - doSearch(reader, weight, filter, hcw); + if (filter == null) { + Scorer scorer = weight.scorer(reader, true, true); + scorer.score(hcw); + } else { + searchWithFilter(reader, weight, filter, hcw); + } return (TopFieldDocs) collector.topDocs(); } - // Search each sub-reader - // TODO: The following should be changed to first obtain a Scorer and then ask it - // if it's going to return in-order or out-of-order docs, and create TSDC - // accordingly. + TopFieldCollector collector = TopFieldCollector.create(sort, nDocs, - fillFields, fieldSortDoTrackScores, fieldSortDoMaxScore, false); + fillFields, fieldSortDoTrackScores, fieldSortDoMaxScore, !weight.scoresDocsOutOfOrder()); search(weight, filter, collector); return (TopFieldDocs) collector.topDocs(); } - // inherit javadoc - /** @deprecated use {@link #search(Weight, Filter, Collector)} instead. */ - public void search(Weight weight, Filter filter, HitCollector results) - throws IOException { - search(weight, filter, new HitCollectorWrapper(results)); - } - - // inherit javadoc - public void search(Weight weight, Filter filter, Collector collector) + public void search(QueryWeight weight, Filter filter, Collector collector) throws IOException { - for (int i = 0; i < subReaders.length; i++) { // search each subreader - collector.setNextReader(subReaders[i], docStarts[i]); - doSearch(subReaders[i], weight, filter, collector); + if (filter == null) { + for (int i = 0; i < subReaders.length; i++) { // search each subreader + collector.setNextReader(subReaders[i], docStarts[i]); + Scorer scorer = weight.scorer(subReaders[i], !collector.acceptsDocsOutOfOrder(), true); + scorer.score(collector); + } + } else { + for (int i = 0; i < subReaders.length; i++) { // search each subreader + collector.setNextReader(subReaders[i], docStarts[i]); + searchWithFilter(subReaders[i], weight, filter, collector); + } } } - - private void doSearch(IndexReader reader, Weight weight, Filter filter, - final Collector collector) throws IOException { - Scorer scorer = weight.scorer(reader); - if (scorer == null) + private void searchWithFilter(IndexReader reader, QueryWeight weight, + final Filter filter, final Collector collector) throws IOException { + + assert filter != null; + + Scorer scorer = weight.scorer(reader, true, false); + if (scorer == null) { return; + } int docID = scorer.docID(); assert docID == -1 || docID == DocIdSetIterator.NO_MORE_DOCS; - - if (filter == null) { - scorer.score(collector); - return; - } // CHECKME: use ConjunctionScorer here? DocIdSetIterator filterIter = filter.getDocIdSet(reader).iterator(); @@ -300,7 +295,7 @@ public class IndexSearcher extends Searcher { return query; } - public Explanation explain(Weight weight, int doc) throws IOException { + public Explanation explain(QueryWeight weight, int doc) throws IOException { return weight.explain(reader, doc); } diff --git a/src/java/org/apache/lucene/search/MatchAllDocsQuery.java b/src/java/org/apache/lucene/search/MatchAllDocsQuery.java index 35ca11622b0..a590781707f 100644 --- a/src/java/org/apache/lucene/search/MatchAllDocsQuery.java +++ b/src/java/org/apache/lucene/search/MatchAllDocsQuery.java @@ -49,7 +49,7 @@ public class MatchAllDocsQuery extends Query { final byte[] norms; private int doc = -1; - MatchAllScorer(IndexReader reader, Similarity similarity, Weight w, + MatchAllScorer(IndexReader reader, Similarity similarity, QueryWeight w, byte[] norms) throws IOException { super(similarity); this.termDocs = reader.termDocs(null); @@ -93,7 +93,7 @@ public class MatchAllDocsQuery extends Query { } } - private class MatchAllDocsWeight implements Weight { + private class MatchAllDocsWeight extends QueryWeight { private Similarity similarity; private float queryWeight; private float queryNorm; @@ -124,7 +124,7 @@ public class MatchAllDocsQuery extends Query { queryWeight *= this.queryNorm; } - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { return new MatchAllScorer(reader, similarity, this, normsField != null ? reader.norms(normsField) : null); } @@ -142,7 +142,7 @@ public class MatchAllDocsQuery extends Query { } } - protected Weight createWeight(Searcher searcher) { + public QueryWeight createQueryWeight(Searcher searcher) { return new MatchAllDocsWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/MultiPhraseQuery.java b/src/java/org/apache/lucene/search/MultiPhraseQuery.java index 04be80c4c90..01683072cf4 100644 --- a/src/java/org/apache/lucene/search/MultiPhraseQuery.java +++ b/src/java/org/apache/lucene/search/MultiPhraseQuery.java @@ -123,7 +123,7 @@ public class MultiPhraseQuery extends Query { } - private class MultiPhraseWeight implements Weight { + private class MultiPhraseWeight extends QueryWeight { private Similarity similarity; private float value; private float idf; @@ -158,7 +158,7 @@ public class MultiPhraseQuery extends Query { value = queryWeight * idf; // idf for document } - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { if (termArrays.size() == 0) // optimize zero-term case return null; @@ -217,7 +217,7 @@ public class MultiPhraseQuery extends Query { fieldExpl.setDescription("fieldWeight("+getQuery()+" in "+doc+ "), product of:"); - Explanation tfExpl = scorer(reader).explain(doc); + Explanation tfExpl = scorer(reader, true, false).explain(doc); fieldExpl.addDetail(tfExpl); fieldExpl.addDetail(idfExpl); @@ -261,7 +261,7 @@ public class MultiPhraseQuery extends Query { } } - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new MultiPhraseWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/MultiSearcher.java b/src/java/org/apache/lucene/search/MultiSearcher.java index 26cbe6ef19a..691c12e19f1 100644 --- a/src/java/org/apache/lucene/search/MultiSearcher.java +++ b/src/java/org/apache/lucene/search/MultiSearcher.java @@ -35,11 +35,12 @@ import java.util.Set; * or {@link #search(Query,Filter)} methods. */ public class MultiSearcher extends Searcher { - /** - * Document Frequency cache acting as a Dummy-Searcher. - * This class is no full-fledged Searcher, but only supports - * the methods necessary to initialize Weights. - */ + + /** + * Document Frequency cache acting as a Dummy-Searcher. This class is no + * full-fledged Searcher, but only supports the methods necessary to + * initialize Weights. + */ private static class CachedDfSource extends Searcher { private Map dfMap; // Map from Terms to corresponding doc freqs private int maxDoc; // document count @@ -93,34 +94,28 @@ public class MultiSearcher extends Searcher { throw new UnsupportedOperationException(); } - public Explanation explain(Weight weight,int doc) { + public Explanation explain(QueryWeight weight,int doc) { throw new UnsupportedOperationException(); } - /** @deprecated use {@link #search(Weight, Filter, Collector)} instead. */ - public void search(Weight weight, Filter filter, HitCollector results) { + public void search(QueryWeight weight, Filter filter, Collector results) { throw new UnsupportedOperationException(); } - public void search(Weight weight, Filter filter, Collector collector) { + public TopDocs search(QueryWeight weight,Filter filter,int n) { throw new UnsupportedOperationException(); } - public TopDocs search(Weight weight,Filter filter,int n) { - throw new UnsupportedOperationException(); - } - - public TopFieldDocs search(Weight weight,Filter filter,int n,Sort sort) { + public TopFieldDocs search(QueryWeight weight,Filter filter,int n,Sort sort) { throw new UnsupportedOperationException(); } } - private Searchable[] searchables; private int[] starts; private int maxDoc = 0; - /** Creates a searcher which searches searchables. */ + /** Creates a searcher which searches searchers. */ public MultiSearcher(Searchable[] searchables) throws IOException { this.searchables = searchables; @@ -136,7 +131,7 @@ public class MultiSearcher extends Searcher { public Searchable[] getSearchables() { return searchables; } - + protected int[] getStarts() { return starts; } @@ -200,8 +195,8 @@ public class MultiSearcher extends Searcher { return maxDoc; } - public TopDocs search(Weight weight, Filter filter, int nDocs) - throws IOException { + public TopDocs search(QueryWeight weight, Filter filter, int nDocs) + throws IOException { HitQueue hq = new HitQueue(nDocs, false); int totalHits = 0; @@ -211,10 +206,10 @@ public class MultiSearcher extends Searcher { totalHits += docs.totalHits; // update totalHits ScoreDoc[] scoreDocs = docs.scoreDocs; for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq - ScoreDoc scoreDoc = scoreDocs[j]; + ScoreDoc scoreDoc = scoreDocs[j]; scoreDoc.doc += starts[i]; // convert doc if(!hq.insert(scoreDoc)) - break; // no more scores > minScore + break; // no more scores > minScore } } @@ -227,7 +222,7 @@ public class MultiSearcher extends Searcher { return new TopDocs(totalHits, scoreDocs, maxScore); } - public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort) + public TopFieldDocs search (QueryWeight weight, Filter filter, int n, Sort sort) throws IOException { FieldDocSortedHitQueue hq = null; int totalHits = 0; @@ -269,14 +264,7 @@ public class MultiSearcher extends Searcher { } // inherit javadoc - /** @deprecated use {@link #search(Weight, Filter, Collector)} instead. */ - public void search(Weight weight, Filter filter, final HitCollector results) - throws IOException { - search(weight, filter, new HitCollectorWrapper(results)); - } - - // inherit javadoc - public void search(Weight weight, Filter filter, final Collector collector) + public void search(QueryWeight weight, Filter filter, final Collector collector) throws IOException { for (int i = 0; i < searchables.length; i++) { @@ -292,6 +280,9 @@ public class MultiSearcher extends Searcher { public void setNextReader(IndexReader reader, int docBase) throws IOException { collector.setNextReader(reader, start + docBase); } + public boolean acceptsDocsOutOfOrder() { + return collector.acceptsDocsOutOfOrder(); + } }; searchables[i].search(weight, filter, hc); @@ -306,9 +297,9 @@ public class MultiSearcher extends Searcher { return queries[0].combine(queries); } - public Explanation explain(Weight weight, int doc) throws IOException { + public Explanation explain(QueryWeight weight, int doc) throws IOException { int i = subSearcher(doc); // find searcher index - return searchables[i].explain(weight,doc-starts[i]); // dispatch to searcher + return searchables[i].explain(weight, doc - starts[i]); // dispatch to searcher } /** @@ -326,7 +317,7 @@ public class MultiSearcher extends Searcher { * * @return rewritten queries */ - protected Weight createWeight(Query original) throws IOException { + protected QueryWeight createQueryWeight(Query original) throws IOException { // step 1 Query rewrittenQuery = rewrite(original); @@ -354,7 +345,7 @@ public class MultiSearcher extends Searcher { int numDocs = maxDoc(); CachedDfSource cacheSim = new CachedDfSource(dfMap, numDocs, getSimilarity()); - return rewrittenQuery.weight(cacheSim); + return rewrittenQuery.queryWeight(cacheSim); } } diff --git a/src/java/org/apache/lucene/search/ParallelMultiSearcher.java b/src/java/org/apache/lucene/search/ParallelMultiSearcher.java index a2efb4eb0f3..54af6cd2e9f 100644 --- a/src/java/org/apache/lucene/search/ParallelMultiSearcher.java +++ b/src/java/org/apache/lucene/search/ParallelMultiSearcher.java @@ -33,11 +33,11 @@ public class ParallelMultiSearcher extends MultiSearcher { private Searchable[] searchables; private int[] starts; - /** Creates a searcher which searches searchables. */ + /** Creates a searchable which searches searchables. */ public ParallelMultiSearcher(Searchable[] searchables) throws IOException { super(searchables); - this.searchables=searchables; - this.starts=getStarts(); + this.searchables = searchables; + this.starts = getStarts(); } /** @@ -52,24 +52,16 @@ public class ParallelMultiSearcher extends MultiSearcher { * Searchable, waits for each search to complete and merge * the results back together. */ - public TopDocs search(Weight weight, Filter filter, int nDocs) + public TopDocs search(QueryWeight weight, Filter filter, int nDocs) throws IOException { HitQueue hq = new HitQueue(nDocs, false); int totalHits = 0; MultiSearcherThread[] msta = new MultiSearcherThread[searchables.length]; - for (int i = 0; i < searchables.length; i++) { // search each searcher + for (int i = 0; i < searchables.length; i++) { // search each searchable // Assume not too many searchables and cost of creating a thread is by far inferior to a search - msta[i] = - new MultiSearcherThread( - searchables[i], - weight, - filter, - nDocs, - hq, - i, - starts, - "MultiSearcher thread #" + (i + 1)); + msta[i] = new MultiSearcherThread(searchables[i], weight, filter, nDocs, + hq, i, starts, "MultiSearcher thread #" + (i + 1)); msta[i].start(); } @@ -105,25 +97,16 @@ public class ParallelMultiSearcher extends MultiSearcher { * Searchable, waits for each search to complete and merges * the results back together. */ - public TopFieldDocs search(Weight weight, Filter filter, int nDocs, Sort sort) + public TopFieldDocs search(QueryWeight weight, Filter filter, int nDocs, Sort sort) throws IOException { // don't specify the fields - we'll wait to do this until we get results FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue (null, nDocs); int totalHits = 0; MultiSearcherThread[] msta = new MultiSearcherThread[searchables.length]; - for (int i = 0; i < searchables.length; i++) { // search each searcher + for (int i = 0; i < searchables.length; i++) { // search each searchable // Assume not too many searchables and cost of creating a thread is by far inferior to a search - msta[i] = - new MultiSearcherThread( - searchables[i], - weight, - filter, - nDocs, - hq, - sort, - i, - starts, - "MultiSearcher thread #" + (i + 1)); + msta[i] = new MultiSearcherThread(searchables[i], weight, filter, nDocs, + hq, sort, i, starts, "MultiSearcher thread #" + (i + 1)); msta[i].start(); } @@ -155,28 +138,6 @@ public class ParallelMultiSearcher extends MultiSearcher { return new TopFieldDocs(totalHits, scoreDocs, hq.getFields(), maxScore); } - /** Lower-level search API. - * - *

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

Applications should only use this if they need all of the - * matching documents. The high-level search API ({@link - * Searcher#search(Query)}) is usually more efficient, as it skips - * non-high-scoring hits. - * - * @param weight to match documents - * @param filter if non-null, a bitset used to eliminate some documents - * @param results to receive hits - * - * @todo parallelize this one too - * @deprecated use {@link #search(Weight, Filter, Collector)} instead. - */ - public void search(Weight weight, Filter filter, final HitCollector results) - throws IOException { - search(weight, filter, new HitCollectorWrapper(results)); - } - /** Lower-level search API. * *

{@link Collector#collect(int)} is called for every matching document. @@ -192,7 +153,7 @@ public class ParallelMultiSearcher extends MultiSearcher { * * @todo parallelize this one too */ - public void search(Weight weight, Filter filter, final Collector collector) + public void search(QueryWeight weight, Filter filter, final Collector collector) throws IOException { for (int i = 0; i < searchables.length; i++) { @@ -205,10 +166,12 @@ public class ParallelMultiSearcher extends MultiSearcher { public void collect(int doc) throws IOException { collector.collect(doc); } - public void setNextReader(IndexReader reader, int docBase) throws IOException { collector.setNextReader(reader, start + docBase); } + public boolean acceptsDocsOutOfOrder() { + return collector.acceptsDocsOutOfOrder(); + } }; searchables[i].search(weight, filter, hc); @@ -231,7 +194,7 @@ public class ParallelMultiSearcher extends MultiSearcher { class MultiSearcherThread extends Thread { private Searchable searchable; - private Weight weight; + private QueryWeight weight; private Filter filter; private int nDocs; private TopDocs docs; @@ -241,15 +204,8 @@ class MultiSearcherThread extends Thread { private IOException ioe; private Sort sort; - public MultiSearcherThread( - Searchable searchable, - Weight weight, - Filter filter, - int nDocs, - HitQueue hq, - int i, - int[] starts, - String name) { + public MultiSearcherThread(Searchable searchable, QueryWeight weight, Filter filter, + int nDocs, HitQueue hq, int i, int[] starts, String name) { super(name); this.searchable = searchable; this.weight = weight; @@ -260,16 +216,9 @@ class MultiSearcherThread extends Thread { this.starts = starts; } - public MultiSearcherThread( - Searchable searchable, - Weight weight, - Filter filter, - int nDocs, - FieldDocSortedHitQueue hq, - Sort sort, - int i, - int[] starts, - String name) { + public MultiSearcherThread(Searchable searchable, QueryWeight weight, + Filter filter, int nDocs, FieldDocSortedHitQueue hq, Sort sort, int i, + int[] starts, String name) { super(name); this.searchable = searchable; this.weight = weight; @@ -298,7 +247,7 @@ class MultiSearcherThread extends Thread { TopFieldDocs docsFields = (TopFieldDocs) docs; // If one of the Sort fields is FIELD_DOC, need to fix its values, so that // it will break ties by doc Id properly. Otherwise, it will compare to - // 'relative' doc Ids, that belong to two different searchers. + // 'relative' doc Ids, that belong to two different searchables. for (int j = 0; j < docsFields.fields.length; j++) { if (docsFields.fields[j].getType() == SortField.DOC) { // iterate over the score docs and change their fields value diff --git a/src/java/org/apache/lucene/search/PhraseQuery.java b/src/java/org/apache/lucene/search/PhraseQuery.java index db850a8f71b..ef76aa2f311 100644 --- a/src/java/org/apache/lucene/search/PhraseQuery.java +++ b/src/java/org/apache/lucene/search/PhraseQuery.java @@ -106,7 +106,7 @@ public class PhraseQuery extends Query { return result; } - private class PhraseWeight implements Weight { + private class PhraseWeight extends QueryWeight { private Similarity similarity; private float value; private float idf; @@ -136,7 +136,7 @@ public class PhraseQuery extends Query { value = queryWeight * idf; // idf for document } - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { if (terms.size() == 0) // optimize zero-term case return null; @@ -209,7 +209,7 @@ public class PhraseQuery extends Query { fieldExpl.setDescription("fieldWeight("+field+":"+query+" in "+doc+ "), product of:"); - Explanation tfExpl = scorer(reader).explain(doc); + Explanation tfExpl = scorer(reader, true, false).explain(doc); fieldExpl.addDetail(tfExpl); fieldExpl.addDetail(idfExpl); @@ -237,12 +237,12 @@ public class PhraseQuery extends Query { } } - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { if (terms.size() == 1) { // optimize one-term case Term term = (Term)terms.get(0); Query termQuery = new TermQuery(term); termQuery.setBoost(getBoost()); - return termQuery.createWeight(searcher); + return termQuery.createQueryWeight(searcher); } return new PhraseWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/PhraseScorer.java b/src/java/org/apache/lucene/search/PhraseScorer.java index 1d4942e65ab..fc338b3be6b 100644 --- a/src/java/org/apache/lucene/search/PhraseScorer.java +++ b/src/java/org/apache/lucene/search/PhraseScorer.java @@ -19,7 +19,7 @@ package org.apache.lucene.search; import java.io.IOException; -import org.apache.lucene.index.*; +import org.apache.lucene.index.TermPositions; /** Expert: Scoring functionality for phrase queries. *
A document is considered matching if it contains the phrase-query terms @@ -32,7 +32,7 @@ import org.apache.lucene.index.*; * means a match. */ abstract class PhraseScorer extends Scorer { - private Weight weight; + private QueryWeight weight; protected byte[] norms; protected float value; @@ -43,7 +43,7 @@ abstract class PhraseScorer extends Scorer { private float freq; //prhase frequency in current doc as computed by phraseFreq(). - PhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, + PhraseScorer(QueryWeight weight, TermPositions[] tps, int[] offsets, Similarity similarity, byte[] norms) { super(similarity); this.norms = norms; diff --git a/src/java/org/apache/lucene/search/PositiveScoresOnlyCollector.java b/src/java/org/apache/lucene/search/PositiveScoresOnlyCollector.java index b5aab42cb53..e13c62fd9dd 100644 --- a/src/java/org/apache/lucene/search/PositiveScoresOnlyCollector.java +++ b/src/java/org/apache/lucene/search/PositiveScoresOnlyCollector.java @@ -26,7 +26,6 @@ import org.apache.lucene.index.IndexReader; * {@link Collector} and makes sure only documents with * scores > 0 are collected. */ - public class PositiveScoresOnlyCollector extends Collector { final private Collector c; @@ -53,4 +52,8 @@ public class PositiveScoresOnlyCollector extends Collector { c.setScorer(this.scorer); } + public boolean acceptsDocsOutOfOrder() { + return c.acceptsDocsOutOfOrder(); + } + } diff --git a/src/java/org/apache/lucene/search/Query.java b/src/java/org/apache/lucene/search/Query.java index a1dd8a1ab27..9fa1b5f2571 100644 --- a/src/java/org/apache/lucene/search/Query.java +++ b/src/java/org/apache/lucene/search/Query.java @@ -80,24 +80,50 @@ public abstract class Query implements java.io.Serializable, Cloneable { return toString(""); } - /** Expert: Constructs an appropriate Weight implementation for this query. - * - *

Only implemented by primitive queries, which re-write to themselves. + /** + * Expert: Constructs an appropriate Weight implementation for this query. + * + *

+ * Only implemented by primitive queries, which re-write to themselves. + * @deprecated use {@link #createQueryWeight(Searcher)} instead. */ protected Weight createWeight(Searcher searcher) throws IOException { + return createQueryWeight(searcher); + } + + /** + * Expert: Constructs an appropriate {@link QueryWeight} implementation for + * this query. + * + *

+ * Only implemented by primitive queries, which re-write to themselves. + */ + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { throw new UnsupportedOperationException(); } - /** Expert: Constructs and initializes a Weight for a top-level query. */ - public Weight weight(Searcher searcher) - throws IOException { + /** + * Expert: Constructs and initializes a Weight for a top-level query. + * + * @deprecated use {@link #queryWeight(Searcher)} instead. + */ + public Weight weight(Searcher searcher) throws IOException { + return queryWeight(searcher); + } + + /** + * Expert: Constructs and initializes a {@link QueryWeight} for a top-level + * query. + */ + public QueryWeight queryWeight(Searcher searcher) throws IOException { Query query = searcher.rewrite(this); - Weight weight = query.createWeight(searcher); + QueryWeight weight = query.createQueryWeight(searcher); float sum = weight.sumOfSquaredWeights(); float norm = getSimilarity(searcher).queryNorm(sum); weight.normalize(norm); return weight; } + /** Expert: called to re-write queries into primitive queries. For example, * a PrefixQuery will be rewritten into a BooleanQuery that consists @@ -106,6 +132,7 @@ public abstract class Query implements java.io.Serializable, Cloneable { public Query rewrite(IndexReader reader) throws IOException { return this; } + /** Expert: called when re-writing queries under MultiSearcher. * @@ -151,6 +178,7 @@ public abstract class Query implements java.io.Serializable, Cloneable { result.add((Query) it.next(), BooleanClause.Occur.SHOULD); return result; } + /** * Expert: adds all terms occuring in this query to the terms set. Only @@ -162,6 +190,7 @@ public abstract class Query implements java.io.Serializable, Cloneable { // needs to be implemented by query subclasses throw new UnsupportedOperationException(); } + /** Expert: merges the clauses of a set of BooleanQuery's into a single @@ -187,6 +216,7 @@ public abstract class Query implements java.io.Serializable, Cloneable { } return result; } + /** Expert: Returns the Similarity implementation to be used for this query. * Subclasses may override this method to specify their own Similarity @@ -199,7 +229,7 @@ public abstract class Query implements java.io.Serializable, Cloneable { /** Returns a clone of this query. */ public Object clone() { try { - return (Query)super.clone(); + return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("Clone not supported: " + e.getMessage()); } diff --git a/src/java/org/apache/lucene/search/QueryWeight.java b/src/java/org/apache/lucene/search/QueryWeight.java new file mode 100644 index 00000000000..69c809e2324 --- /dev/null +++ b/src/java/org/apache/lucene/search/QueryWeight.java @@ -0,0 +1,119 @@ +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 java.io.Serializable; + +import org.apache.lucene.index.IndexReader; + +/** + * Expert: Calculate query weights and build query scorers. + *

+ * The purpose of {@link QueryWeight} is to ensure searching does not + * modify a {@link Query}, so that a {@link Query} instance can be reused.
+ * {@link Searcher} dependent state of the query should reside in the + * {@link QueryWeight}.
+ * {@link IndexReader} dependent state should reside in the {@link Scorer}. + *

+ * A QueryWeight is used in the following way: + *

    + *
  1. A QueryWeight is constructed by a top-level query, given a + * Searcher ({@link Query#createWeight(Searcher)}). + *
  2. The {@link #sumOfSquaredWeights()} method is called on the + * QueryWeight to compute the query normalization factor + * {@link Similarity#queryNorm(float)} of the query clauses contained in the + * query. + *
  3. The query normalization factor is passed to {@link #normalize(float)}. At + * this point the weighting is complete. + *
  4. A Scorer is constructed by {@link #scorer(IndexReader)}. + *
+ * + * @since 2.9 + */ +public abstract class QueryWeight implements Weight, Serializable { + + /** An explanation of the score computation for the named document. */ + public abstract Explanation explain(IndexReader reader, int doc) throws IOException; + + /** The query that this concerns. */ + public abstract Query getQuery(); + + /** The weight for this query. */ + public abstract float getValue(); + + /** Assigns the query normalization factor to this. */ + public abstract void normalize(float norm); + + /** + * @deprecated use {@link #scorer(IndexReader, boolean, boolean)} instead. + * Currently this defaults to asking a scorer in out-of-order + * mode, but will be removed in 3.0. + */ + public Scorer scorer(IndexReader reader) throws IOException { + return scorer(reader, true, false); + } + + /** + * Returns a {@link Scorer} which scores documents in/out-of order according + * to scoreDocsInOrder. + *

+ * NOTE: even if scoreDocsInOrder is false, it is + * recommended to check whether the returned Scorer indeed scores + * documents out of order (i.e., call {@link #scoresDocsOutOfOrder()}), as some + * Scorer implementations will always return documents in-order. + * + * @param reader + * the {@link IndexReader} for which to return the {@link Scorer}. + * @param scoreDocsInOrder + * specifies whether in-order scoring of documents is required. Note + * that if set to false (i.e., out-of-order scoring is required), + * this method can return whatever scoring mode it supports, as every + * in-order scorer is also an out-of-order one. However, an + * out-of-order scorer may not support {@link Scorer#nextDoc()} + * and/or {@link Scorer#advance(int)}, therfore it is recommended to + * request an in-order scorer if use of these methods is required. + * @param topScorer + * specifies whether the returned {@link Scorer} will be used as a + * top scorer or as in iterator. I.e., if true, + * {@link Scorer#score(Collector)} will be called; if false, + * {@link Scorer#nextDoc()} and/or {@link Scorer#advance(int)} will + * be called. + * @return a {@link Scorer} which scores documents in/out-of order. + * @throws IOException + */ + public abstract Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, + boolean topScorer) throws IOException; + + /** The sum of squared weights of contained query clauses. */ + public abstract float sumOfSquaredWeights() throws IOException; + + /** + * Returns true iff this implementation scores docs only out of order. This + * method is used in conjunction with {@link Collector}'s + * {@link Collector#acceptsDocsOutOfOrder() acceptsDocsOutOfOrder} and + * {@link #scorer(org.apache.lucene.index.IndexReader, boolean, boolean)} to + * create a matching {@link Scorer} instance for a given {@link Collector}, or + * vice versa. + *

+ * NOTE: the default implementation returns false, i.e. + * the Scorer scores documents in-order. + */ + public boolean scoresDocsOutOfOrder() { return false; } + +} diff --git a/src/java/org/apache/lucene/search/QueryWeightWrapper.java b/src/java/org/apache/lucene/search/QueryWeightWrapper.java new file mode 100644 index 00000000000..5f92ef775c1 --- /dev/null +++ b/src/java/org/apache/lucene/search/QueryWeightWrapper.java @@ -0,0 +1,68 @@ +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; + +/** + * A wrapper class for the deprecated {@link Weight}. + * Please re-implement any custom Weight classes as {@link + * QueryWeight} instead. + * + * @deprecated will be removed in 3.0 + */ +public class QueryWeightWrapper extends QueryWeight { + + private Weight weight; + + public QueryWeightWrapper(Weight weight) { + this.weight = weight; + } + + public Explanation explain(IndexReader reader, int doc) throws IOException { + return weight.explain(reader, doc); + } + + public Query getQuery() { + return weight.getQuery(); + } + + public float getValue() { + return weight.getValue(); + } + + public void normalize(float norm) { + weight.normalize(norm); + } + + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) + throws IOException { + return weight.scorer(reader); + } + + public float sumOfSquaredWeights() throws IOException { + return weight.sumOfSquaredWeights(); + } + + public Scorer scorer(IndexReader reader) throws IOException { + return weight.scorer(reader); + } + +} diff --git a/src/java/org/apache/lucene/search/QueryWrapperFilter.java b/src/java/org/apache/lucene/search/QueryWrapperFilter.java index 75959e7d7a2..d697482a419 100644 --- a/src/java/org/apache/lucene/search/QueryWrapperFilter.java +++ b/src/java/org/apache/lucene/search/QueryWrapperFilter.java @@ -61,15 +61,18 @@ public class QueryWrapperFilter extends Filter { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); return bits; } public DocIdSet getDocIdSet(final IndexReader reader) throws IOException { - final Weight weight = query.weight(new IndexSearcher(reader)); + final QueryWeight weight = query.queryWeight(new IndexSearcher(reader)); return new DocIdSet() { public DocIdSetIterator iterator() throws IOException { - return weight.scorer(reader); + return weight.scorer(reader, true, false); } }; } diff --git a/src/java/org/apache/lucene/search/Searchable.java b/src/java/org/apache/lucene/search/Searchable.java index d5bbad38087..3aaab1fe55d 100644 --- a/src/java/org/apache/lucene/search/Searchable.java +++ b/src/java/org/apache/lucene/search/Searchable.java @@ -17,25 +17,32 @@ package org.apache.lucene.search; * 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.IndexReader; // for javadoc -import org.apache.lucene.index.Term; import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.Term; -import java.io.IOException; // for javadoc - -/** The interface for search implementations. - * - *

Searchable is the abstract network protocol for searching. - * Implementations provide search over a single index, over multiple - * indices, and over indices on remote servers. - * - *

Queries, filters and sort criteria are designed to be compact so that - * they may be efficiently passed to a remote index, with only the top-scoring - * hits being returned, rather than every matching hit. +/** + * The interface for search implementations. + * + *

+ * Searchable is the abstract network protocol for searching. Implementations + * provide search over a single index, over multiple indices, and over indices + * on remote servers. + * + *

+ * Queries, filters and sort criteria are designed to be compact so that they + * may be efficiently passed to a remote index, with only the top-scoring hits + * being returned, rather than every matching hit. + * + * NOTE: this interface is kept public for convenience. Since it is not + * expected to be implemented directly, it may be changed unexpectedly between + * releases. */ public interface Searchable { + /** Lower-level search API. * *

{@link HitCollector#collect(int,float)} is called for every non-zero @@ -51,7 +58,7 @@ public interface Searchable { * @param filter if non-null, used to permit documents to be collected. * @param results to receive hits * @throws BooleanQuery.TooManyClauses - * @deprecated use {@link #search(Weight, Filter, Collector)} instead. + * @deprecated use {@link #search(QueryWeight, Filter, Collector)} instead. */ void search(Weight weight, Filter filter, HitCollector results) throws IOException; @@ -75,9 +82,33 @@ public interface Searchable { * @param collector * to receive hits * @throws BooleanQuery.TooManyClauses + * + * @deprecated use {@link #search(QueryWeight, Filter, Collector)} instead. */ void search(Weight weight, Filter filter, Collector collector) throws IOException; + /** + * Lower-level search API. + * + *

+ * {@link Collector#collect(int)} is called for every document.
+ * Collector-based access to remote indexes is discouraged. + * + *

+ * Applications should only use this if they need all of the matching + * documents. The high-level search API ({@link Searcher#search(Query)}) is + * usually more efficient, as it skips non-high-scoring hits. + * + * @param weight + * to match documents + * @param filter + * if non-null, used to permit documents to be collected. + * @param collector + * to receive hits + * @throws BooleanQuery.TooManyClauses + */ + void search(QueryWeight weight, Filter filter, Collector collector) throws IOException; + /** Frees resources associated with this Searcher. * Be careful not to call this method while you are still using objects * like {@link Hits}. @@ -86,7 +117,7 @@ public interface Searchable { /** Expert: Returns the number of documents containing term. * Called by search code to compute term weights. - * @see IndexReader#docFreq(Term) + * @see org.apache.lucene.index.IndexReader#docFreq(Term) */ int docFreq(Term term) throws IOException; @@ -98,7 +129,7 @@ public interface Searchable { /** Expert: Returns one greater than the largest possible document number. * Called by search code to compute term weights. - * @see IndexReader#maxDoc() + * @see org.apache.lucene.index.IndexReader#maxDoc() */ int maxDoc() throws IOException; @@ -110,12 +141,24 @@ public interface Searchable { *

Applications should usually call {@link Searcher#search(Query)} or * {@link Searcher#search(Query,Filter)} instead. * @throws BooleanQuery.TooManyClauses + * @deprecated use {@link #search(QueryWeight, Filter, int)} instead. */ TopDocs search(Weight weight, Filter filter, int n) throws IOException; + + /** Expert: Low-level search implementation. Finds the top n + * hits for query, applying filter if non-null. + * + *

Called by {@link Hits}. + * + *

Applications should usually call {@link Searcher#search(Query)} or + * {@link Searcher#search(Query,Filter)} instead. + * @throws BooleanQuery.TooManyClauses + */ + TopDocs search(QueryWeight weight, Filter filter, int n) throws IOException; /** Expert: Returns the stored fields of document i. * Called by {@link HitCollector} implementations. - * @see IndexReader#document(int) + * @see org.apache.lucene.index.IndexReader#document(int) * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error */ @@ -136,7 +179,7 @@ public interface Searchable { * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error * - * @see IndexReader#document(int, FieldSelector) + * @see org.apache.lucene.index.IndexReader#document(int, FieldSelector) * @see org.apache.lucene.document.Fieldable * @see org.apache.lucene.document.FieldSelector * @see org.apache.lucene.document.SetBasedFieldSelector @@ -159,10 +202,23 @@ public interface Searchable { * entire index. *

Applications should call {@link Searcher#explain(Query, int)}. * @throws BooleanQuery.TooManyClauses + * @deprecated use {@link #explain(QueryWeight, int)} instead. */ Explanation explain(Weight weight, int doc) throws IOException; + + /** Expert: low-level implementation method + * Returns an Explanation that describes how doc scored against + * weight. + * + *

This is intended to be used in developing Similarity implementations, + * and, for good performance, should not be displayed with every hit. + * Computing an explanation is as expensive as executing the query over the + * entire index. + *

Applications should call {@link Searcher#explain(Query, int)}. + * @throws BooleanQuery.TooManyClauses + */ + Explanation explain(QueryWeight weight, int doc) throws IOException; - // TODO: change the javadoc in 3.0 to remove the last NOTE section. /** Expert: Low-level search implementation with arbitrary sorting. Finds * the top n hits for query, applying * filter if non-null, and sorting the hits by the criteria in @@ -171,15 +227,23 @@ public interface Searchable { *

Applications should usually call {@link * Searcher#search(Query,Filter,Sort)} instead. * - * NOTE: currently, this method tracks document scores and sets them in - * the returned {@link FieldDoc}, however in 3.0 it will move to not track - * document scores. If document scores tracking is still needed, you can use - * {@link #search(Weight, Filter, Collector)} and pass in a - * {@link TopFieldCollector} instance. - * * @throws BooleanQuery.TooManyClauses + * @deprecated use {@link #search(QueryWeight, Filter, int, Sort)} instead. */ TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) throws IOException; + + /** Expert: Low-level search implementation with arbitrary sorting. Finds + * the top n hits for query, applying + * filter if non-null, and sorting the hits by the criteria in + * sort. + * + *

Applications should usually call {@link + * Searcher#search(Query,Filter,Sort)} instead. + * + * @throws BooleanQuery.TooManyClauses + */ + TopFieldDocs search(QueryWeight weight, Filter filter, int n, Sort sort) + throws IOException; } diff --git a/src/java/org/apache/lucene/search/Searcher.java b/src/java/org/apache/lucene/search/Searcher.java index c0fa26d8f20..a779971d4cf 100644 --- a/src/java/org/apache/lucene/search/Searcher.java +++ b/src/java/org/apache/lucene/search/Searcher.java @@ -19,15 +19,17 @@ package org.apache.lucene.search; import java.io.IOException; +import org.apache.lucene.document.Document; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.Term; -import org.apache.lucene.document.Document; -/** An abstract base class for search implementations. - * Implements the main search methods. +/** + * An abstract base class for search implementations. Implements the main search + * methods. * - *

Note that you can only access Hits from a Searcher as long as it is - * not yet closed, otherwise an IOException will be thrown. + *

+ * Note that you can only access hits from a Searcher as long as it is not yet + * closed, otherwise an IOException will be thrown. */ public abstract class Searcher implements Searchable { @@ -87,7 +89,7 @@ public abstract class Searcher implements Searchable { */ public TopFieldDocs search(Query query, Filter filter, int n, Sort sort) throws IOException { - return search(createWeight(query), filter, n, sort); + return search(createQueryWeight(query), filter, n, sort); } /** Lower-level search API. @@ -107,7 +109,7 @@ public abstract class Searcher implements Searchable { */ public void search(Query query, HitCollector results) throws IOException { - search(query, (Filter)null, results); + search(createQueryWeight(query), null, new HitCollectorWrapper(results)); } /** Lower-level search API. @@ -125,7 +127,7 @@ public abstract class Searcher implements Searchable { */ public void search(Query query, Collector results) throws IOException { - search(query, (Filter)null, results); + search(createQueryWeight(query), null, results); } /** Lower-level search API. @@ -147,7 +149,7 @@ public abstract class Searcher implements Searchable { */ public void search(Query query, Filter filter, HitCollector results) throws IOException { - search(createWeight(query), filter, results); + search(createQueryWeight(query), filter, new HitCollectorWrapper(results)); } /** Lower-level search API. @@ -168,7 +170,7 @@ public abstract class Searcher implements Searchable { */ public void search(Query query, Filter filter, Collector results) throws IOException { - search(createWeight(query), filter, results); + search(createQueryWeight(query), filter, results); } /** Finds the top n @@ -178,7 +180,7 @@ public abstract class Searcher implements Searchable { */ public TopDocs search(Query query, Filter filter, int n) throws IOException { - return search(createWeight(query), filter, n); + return search(createQueryWeight(query), filter, n); } /** Finds the top n @@ -200,7 +202,7 @@ public abstract class Searcher implements Searchable { * entire index. */ public Explanation explain(Query query, int doc) throws IOException { - return explain(createWeight(query), doc); + return explain(createQueryWeight(query), doc); } /** The Similarity implementation used by this searcher. */ @@ -213,7 +215,7 @@ public abstract class Searcher implements Searchable { public void setSimilarity(Similarity similarity) { this.similarity = similarity; } - + /** Expert: Return the Similarity implementation used by this Searcher. * *

This defaults to the current value of {@link Similarity#getDefault()}. @@ -224,10 +226,15 @@ public abstract class Searcher implements Searchable { /** * creates a weight for query - * @return new weight + * + * @deprecated use {@link #createQueryWeight(Query)} instead. */ protected Weight createWeight(Query query) throws IOException { - return query.weight(this); + return createQueryWeight(query); + } + + protected QueryWeight createQueryWeight(Query query) throws IOException { + return query.queryWeight(this); } // inherit javadoc @@ -245,15 +252,34 @@ public abstract class Searcher implements Searchable { /** * @deprecated use {@link #search(Weight, Filter, Collector)} instead. */ - abstract public void search(Weight weight, Filter filter, HitCollector results) throws IOException; - abstract public void search(Weight weight, Filter filter, Collector results) throws IOException; + public void search(Weight weight, Filter filter, HitCollector results) throws IOException { + search(new QueryWeightWrapper(weight), filter, new HitCollectorWrapper(results)); + } + /** @deprecated delete in 3.0. */ + public void search(Weight weight, Filter filter, Collector collector) + throws IOException { + search(new QueryWeightWrapper(weight), filter, collector); + } + abstract public void search(QueryWeight weight, Filter filter, Collector results) throws IOException; abstract public void close() throws IOException; abstract public int docFreq(Term term) throws IOException; abstract public int maxDoc() throws IOException; - abstract public TopDocs search(Weight weight, Filter filter, int n) throws IOException; + /** @deprecated use {@link #search(QueryWeight, Filter, int)} instead. */ + public TopDocs search(Weight weight, Filter filter, int n) throws IOException { + return search(new QueryWeightWrapper(weight), filter, n); + } + abstract public TopDocs search(QueryWeight weight, Filter filter, int n) throws IOException; abstract public Document doc(int i) throws CorruptIndexException, IOException; abstract public Query rewrite(Query query) throws IOException; - abstract public Explanation explain(Weight weight, int doc) throws IOException; - abstract public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) throws IOException; + /** @deprecated use {@link #explain(QueryWeight, int)} instead. */ + public Explanation explain(Weight weight, int doc) throws IOException { + return explain(new QueryWeightWrapper(weight), doc); + } + abstract public Explanation explain(QueryWeight weight, int doc) throws IOException; + /** @deprecated use {@link #search(QueryWeight, Filter, int, Sort)} instead. */ + public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) throws IOException { + return search(new QueryWeightWrapper(weight), filter, n, sort); + } + abstract public TopFieldDocs search(QueryWeight weight, Filter filter, int n, Sort sort) throws IOException; /* End patch for GCJ bug #15411. */ } diff --git a/src/java/org/apache/lucene/search/SloppyPhraseScorer.java b/src/java/org/apache/lucene/search/SloppyPhraseScorer.java index 2778ae8a55a..1ca23140c4b 100644 --- a/src/java/org/apache/lucene/search/SloppyPhraseScorer.java +++ b/src/java/org/apache/lucene/search/SloppyPhraseScorer.java @@ -28,7 +28,7 @@ final class SloppyPhraseScorer extends PhraseScorer { private PhrasePositions tmpPos[]; // for flipping repeating pps. private boolean checkedRepeats; - SloppyPhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, Similarity similarity, + SloppyPhraseScorer(QueryWeight weight, TermPositions[] tps, int[] offsets, Similarity similarity, int slop, byte[] norms) { super(weight, tps, offsets, similarity, norms); this.slop = slop; diff --git a/src/java/org/apache/lucene/search/TermQuery.java b/src/java/org/apache/lucene/search/TermQuery.java index 6f7c0e3750e..80b521709e5 100644 --- a/src/java/org/apache/lucene/search/TermQuery.java +++ b/src/java/org/apache/lucene/search/TermQuery.java @@ -31,7 +31,7 @@ import org.apache.lucene.util.ToStringUtils; public class TermQuery extends Query { private Term term; - private class TermWeight implements Weight { + private class TermWeight extends QueryWeight { private Similarity similarity; private float value; private float idf; @@ -60,14 +60,13 @@ public class TermQuery extends Query { value = queryWeight * idf; // idf for document } - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { TermDocs termDocs = reader.termDocs(term); if (termDocs == null) return null; - return new TermScorer(this, termDocs, similarity, - reader.norms(term.field())); + return new TermScorer(this, termDocs, similarity, reader.norms(term.field())); } public Explanation explain(IndexReader reader, int doc) @@ -104,7 +103,7 @@ public class TermQuery extends Query { fieldExpl.setDescription("fieldWeight("+term+" in "+doc+ "), product of:"); - Explanation tfExpl = scorer(reader).explain(doc); + Explanation tfExpl = scorer(reader, true, false).explain(doc); fieldExpl.addDetail(tfExpl); fieldExpl.addDetail(idfExpl); @@ -142,7 +141,7 @@ public class TermQuery extends Query { /** Returns the term of this query. */ public Term getTerm() { return term; } - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new TermWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/TermScorer.java b/src/java/org/apache/lucene/search/TermScorer.java index b343df7d8ad..86bbba796c1 100644 --- a/src/java/org/apache/lucene/search/TermScorer.java +++ b/src/java/org/apache/lucene/search/TermScorer.java @@ -27,7 +27,7 @@ final class TermScorer extends Scorer { private static final float[] SIM_NORM_DECODER = Similarity.getNormDecoder(); - private Weight weight; + private QueryWeight weight; private TermDocs termDocs; private byte[] norms; private float weightValue; @@ -41,13 +41,41 @@ final class TermScorer extends Scorer { private static final int SCORE_CACHE_SIZE = 32; private float[] scoreCache = new float[SCORE_CACHE_SIZE]; - /** Construct a TermScorer. - * @param weight The weight of the Term in the query. - * @param td An iterator over the documents matching the Term. - * @param similarity The Similarity implementation to be used for score computations. - * @param norms The field norms of the document fields for the Term. + /** + * Construct a TermScorer. + * + * @param weight + * The weight of the Term in the query. + * @param td + * An iterator over the documents matching the Term. + * @param similarity + * The Similarity implementation to be used for score + * computations. + * @param norms + * The field norms of the document fields for the Term. + * + * @deprecated use delete in 3.0, kept around for TestTermScorer in tag which + * creates TermScorer directly, and cannot pass in a QueryWeight + * object. */ - TermScorer(Weight weight, TermDocs td, Similarity similarity, + TermScorer(Weight weight, TermDocs td, Similarity similarity, byte[] norms) { + this(new QueryWeightWrapper(weight), td, similarity, norms); + } + + /** + * Construct a TermScorer. + * + * @param weight + * The weight of the Term in the query. + * @param td + * An iterator over the documents matching the Term. + * @param similarity + * The Similarity implementation to be used for score + * computations. + * @param norms + * The field norms of the document fields for the Term. + */ + TermScorer(QueryWeight weight, TermDocs td, Similarity similarity, byte[] norms) { super(similarity); this.weight = weight; @@ -194,7 +222,7 @@ final class TermScorer extends Scorer { * @param doc The document number for the explanation. */ public Explanation explain(int doc) throws IOException { - TermQuery query = (TermQuery)weight.getQuery(); + TermQuery query = (TermQuery) weight.getQuery(); Explanation tfExplanation = new Explanation(); int tf = 0; while (pointer < pointerMax) { diff --git a/src/java/org/apache/lucene/search/TimeLimitingCollector.java b/src/java/org/apache/lucene/search/TimeLimitingCollector.java index b369183da9c..a67b9f2133e 100644 --- a/src/java/org/apache/lucene/search/TimeLimitingCollector.java +++ b/src/java/org/apache/lucene/search/TimeLimitingCollector.java @@ -216,4 +216,8 @@ public class TimeLimitingCollector extends Collector { collector.setScorer(scorer); } + public boolean acceptsDocsOutOfOrder() { + return collector.acceptsDocsOutOfOrder(); + } + } diff --git a/src/java/org/apache/lucene/search/TopFieldCollector.java b/src/java/org/apache/lucene/search/TopFieldCollector.java index 88d814f2230..d4d23d9cf49 100644 --- a/src/java/org/apache/lucene/search/TopFieldCollector.java +++ b/src/java/org/apache/lucene/search/TopFieldCollector.java @@ -135,6 +135,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { } } } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } /* @@ -240,6 +245,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { } } } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } /* @@ -341,8 +351,12 @@ public abstract class TopFieldCollector extends TopDocsCollector { comparator.setBottom(bottom.slot); } } - } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } /* @@ -489,6 +503,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { } } } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } /* @@ -632,6 +651,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { } } } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } /* @@ -781,6 +805,11 @@ public abstract class TopFieldCollector extends TopDocsCollector { this.scorer = scorer; super.setScorer(scorer); } + + public boolean acceptsDocsOutOfOrder() { + return true; + } + } private static final ScoreDoc[] EMPTY_SCOREDOCS = new ScoreDoc[0]; @@ -930,4 +959,8 @@ public abstract class TopFieldCollector extends TopDocsCollector { return new TopFieldDocs(totalHits, results, ((FieldValueHitQueue) pq).getFields(), maxScore); } + public boolean acceptsDocsOutOfOrder() { + return false; + } + } diff --git a/src/java/org/apache/lucene/search/TopScoreDocCollector.java b/src/java/org/apache/lucene/search/TopScoreDocCollector.java index 9b049f3f4fd..c9cd4e639a3 100644 --- a/src/java/org/apache/lucene/search/TopScoreDocCollector.java +++ b/src/java/org/apache/lucene/search/TopScoreDocCollector.java @@ -55,6 +55,10 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { pqTop.score = score; pqTop = (ScoreDoc) pq.updateTop(); } + + public boolean acceptsDocsOutOfOrder() { + return false; + } } // Assumes docs are scored out of order. @@ -74,6 +78,10 @@ public abstract class TopScoreDocCollector extends TopDocsCollector { pqTop.score = score; pqTop = (ScoreDoc) pq.updateTop(); } + + public boolean acceptsDocsOutOfOrder() { + return true; + } } /** diff --git a/src/java/org/apache/lucene/search/Weight.java b/src/java/org/apache/lucene/search/Weight.java index 69e8b6f3eb9..e90709d222d 100644 --- a/src/java/org/apache/lucene/search/Weight.java +++ b/src/java/org/apache/lucene/search/Weight.java @@ -40,6 +40,8 @@ import org.apache.lucene.index.IndexReader; * At this point the weighting is complete. *

  • A Scorer is constructed by {@link #scorer(IndexReader)}. * + * + * @deprecated use {@link QueryWeight} instead. */ public interface Weight extends java.io.Serializable { /** The query that this concerns. */ diff --git a/src/java/org/apache/lucene/search/function/CustomScoreQuery.java b/src/java/org/apache/lucene/search/function/CustomScoreQuery.java index b02f04572d5..a7950d91721 100755 --- a/src/java/org/apache/lucene/search/function/CustomScoreQuery.java +++ b/src/java/org/apache/lucene/search/function/CustomScoreQuery.java @@ -24,10 +24,10 @@ import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.ComplexExplanation; import org.apache.lucene.search.Explanation; import org.apache.lucene.search.Query; +import org.apache.lucene.search.QueryWeight; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Searcher; import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Weight; import org.apache.lucene.util.ToStringUtils; /** @@ -271,19 +271,18 @@ public class CustomScoreQuery extends Query { //=========================== W E I G H T ============================ - private class CustomWeight implements Weight { + private class CustomWeight extends QueryWeight { Similarity similarity; - Weight subQueryWeight; - Weight[] valSrcWeights; + QueryWeight subQueryWeight; + QueryWeight[] valSrcWeights; boolean qStrict; public CustomWeight(Searcher searcher) throws IOException { this.similarity = getSimilarity(searcher); - this.subQueryWeight = subQuery.weight(searcher); - this.subQueryWeight = subQuery.weight(searcher); - this.valSrcWeights = new Weight[valSrcQueries.length]; + this.subQueryWeight = subQuery.queryWeight(searcher); + this.valSrcWeights = new QueryWeight[valSrcQueries.length]; for(int i = 0; i < valSrcQueries.length; i++) { - this.valSrcWeights[i] = valSrcQueries[i].createWeight(searcher); + this.valSrcWeights[i] = valSrcQueries[i].createQueryWeight(searcher); } this.qStrict = strict; } @@ -325,20 +324,28 @@ public class CustomScoreQuery extends Query { } } - /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */ - public Scorer scorer(IndexReader reader) throws IOException { - Scorer subQueryScorer = subQueryWeight.scorer(reader); + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { + // Pass true for "scoresDocsInOrder", because we + // require in-order scoring, even if caller does not, + // since we call advance on the valSrcScorers. Pass + // false for "topScorer" because we will not invoke + // score(Collector) on these scorers: + Scorer subQueryScorer = subQueryWeight.scorer(reader, true, false); Scorer[] valSrcScorers = new Scorer[valSrcWeights.length]; for(int i = 0; i < valSrcScorers.length; i++) { - valSrcScorers[i] = valSrcWeights[i].scorer(reader); + valSrcScorers[i] = valSrcWeights[i].scorer(reader, true, false); } return new CustomScorer(similarity, reader, this, subQueryScorer, valSrcScorers); } - /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */ public Explanation explain(IndexReader reader, int doc) throws IOException { - return scorer(reader).explain(doc); + return scorer(reader, true, false).explain(doc); } + + public boolean scoresDocsOutOfOrder() { + return false; + } + } @@ -435,8 +442,7 @@ public class CustomScoreQuery extends Query { } } - /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */ - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new CustomWeight(searcher); } diff --git a/src/java/org/apache/lucene/search/function/ValueSourceQuery.java b/src/java/org/apache/lucene/search/function/ValueSourceQuery.java index bc39d608218..02171e6c7e7 100644 --- a/src/java/org/apache/lucene/search/function/ValueSourceQuery.java +++ b/src/java/org/apache/lucene/search/function/ValueSourceQuery.java @@ -62,7 +62,7 @@ public class ValueSourceQuery extends Query { // no terms involved here } - private class ValueSourceWeight implements Weight { + private class ValueSourceWeight extends QueryWeight { Similarity similarity; float queryNorm; float queryWeight; @@ -93,14 +93,13 @@ public class ValueSourceQuery extends Query { queryWeight *= this.queryNorm; } - /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */ - public Scorer scorer(IndexReader reader) throws IOException { + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { return new ValueSourceScorer(similarity, reader, this); } /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */ public Explanation explain(IndexReader reader, int doc) throws IOException { - return scorer(reader).explain(doc); + return scorer(reader, true, false).explain(doc); } } @@ -173,12 +172,10 @@ public class ValueSourceQuery extends Query { } } - /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */ - protected Weight createWeight(Searcher searcher) { + public QueryWeight createQueryWeight(Searcher searcher) { return new ValueSourceQuery.ValueSourceWeight(searcher); } - /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */ public String toString(String field) { return valSrc.toString() + ToStringUtils.boost(getBoost()); } diff --git a/src/java/org/apache/lucene/search/payloads/BoostingTermQuery.java b/src/java/org/apache/lucene/search/payloads/BoostingTermQuery.java index 7f5af8fe10e..c9a80c062aa 100644 --- a/src/java/org/apache/lucene/search/payloads/BoostingTermQuery.java +++ b/src/java/org/apache/lucene/search/payloads/BoostingTermQuery.java @@ -41,29 +41,23 @@ import java.io.IOException; */ public class BoostingTermQuery extends SpanTermQuery{ - public BoostingTermQuery(Term term) { super(term); } - - protected Weight createWeight(Searcher searcher) throws IOException { + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new BoostingTermWeight(this, searcher); } - protected class BoostingTermWeight extends SpanWeight implements Weight { - + protected class BoostingTermWeight extends SpanWeight { public BoostingTermWeight(BoostingTermQuery query, Searcher searcher) throws IOException { super(query, searcher); } - - - - public Scorer scorer(IndexReader reader) throws IOException { - return new BoostingSpanScorer((TermSpans)query.getSpans(reader), this, similarity, - reader.norms(query.getField())); + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { + return new BoostingSpanScorer((TermSpans) query.getSpans(reader), this, + similarity, reader.norms(query.getField())); } protected class BoostingSpanScorer extends SpanScorer { @@ -74,7 +68,7 @@ public class BoostingTermQuery extends SpanTermQuery{ protected float payloadScore; private int payloadsSeen; - public BoostingSpanScorer(TermSpans spans, Weight weight, + public BoostingSpanScorer(TermSpans spans, QueryWeight weight, Similarity similarity, byte[] norms) throws IOException { super(spans, weight, similarity, norms); positions = spans.getPositions(); diff --git a/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java b/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java index 6bf8b906203..7314e684a0d 100644 --- a/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java +++ b/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java @@ -23,9 +23,9 @@ import java.util.Set; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.Query; +import org.apache.lucene.search.QueryWeight; import org.apache.lucene.search.Searcher; import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Weight; import org.apache.lucene.util.ToStringUtils; /** @@ -97,6 +97,7 @@ public class FieldMaskingSpanQuery extends SpanQuery { return maskedQuery.getPayloadSpans(reader); } + /** @deprecated use {@link #extractTerms(Set)} instead. */ public Collection getTerms() { return maskedQuery.getTerms(); } @@ -105,8 +106,8 @@ public class FieldMaskingSpanQuery extends SpanQuery { maskedQuery.extractTerms(terms); } - protected Weight createWeight(Searcher searcher) throws IOException { - return maskedQuery.createWeight(searcher); + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { + return maskedQuery.createQueryWeight(searcher); } public Similarity getSimilarity(Searcher searcher) { diff --git a/src/java/org/apache/lucene/search/spans/SpanQuery.java b/src/java/org/apache/lucene/search/spans/SpanQuery.java index 8a316848b5c..ee290d307db 100644 --- a/src/java/org/apache/lucene/search/spans/SpanQuery.java +++ b/src/java/org/apache/lucene/search/spans/SpanQuery.java @@ -17,14 +17,14 @@ package org.apache.lucene.search.spans; * limitations under the License. */ -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Searcher; -import org.apache.lucene.search.Weight; - import java.io.IOException; import java.util.Collection; -import java.util.Set; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.QueryWeight; +import org.apache.lucene.search.Searcher; +import org.apache.lucene.search.Weight; /** Base class for span-based queries. */ public abstract class SpanQuery extends Query { @@ -46,7 +46,7 @@ public abstract class SpanQuery extends Query { */ public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException{ return null; - }; + } /** Returns the name of the field matched by this query.*/ public abstract String getField(); @@ -57,9 +57,13 @@ public abstract class SpanQuery extends Query { */ public abstract Collection getTerms(); + /** @deprecated delete in 3.0. */ protected Weight createWeight(Searcher searcher) throws IOException { + return createQueryWeight(searcher); + } + + public QueryWeight createQueryWeight(Searcher searcher) throws IOException { return new SpanWeight(this, searcher); } } - diff --git a/src/java/org/apache/lucene/search/spans/SpanScorer.java b/src/java/org/apache/lucene/search/spans/SpanScorer.java index 23f1f79e599..f1f1c4ff410 100644 --- a/src/java/org/apache/lucene/search/spans/SpanScorer.java +++ b/src/java/org/apache/lucene/search/spans/SpanScorer.java @@ -17,19 +17,21 @@ package org.apache.lucene.search.spans; * limitations under the License. */ +import java.io.IOException; + import org.apache.lucene.search.Explanation; +import org.apache.lucene.search.QueryWeight; +import org.apache.lucene.search.QueryWeightWrapper; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.Weight; -import java.io.IOException; - /** * Public for extension only. */ public class SpanScorer extends Scorer { protected Spans spans; - protected Weight weight; + protected QueryWeight weight; protected byte[] norms; protected float value; @@ -40,8 +42,14 @@ public class SpanScorer extends Scorer { protected int doc; protected float freq; + /** @deprecated use {@link #SpanScorer(Spans, QueryWeight, Similarity, byte[])} instead.*/ protected SpanScorer(Spans spans, Weight weight, Similarity similarity, byte[] norms) throws IOException { + this(spans, new QueryWeightWrapper(weight), similarity, norms); + } + + protected SpanScorer(Spans spans, QueryWeight weight, Similarity similarity, byte[] norms) + throws IOException { super(similarity); this.spans = spans; this.norms = norms; diff --git a/src/java/org/apache/lucene/search/spans/SpanWeight.java b/src/java/org/apache/lucene/search/spans/SpanWeight.java index b0037fa9ebf..46ea1622af2 100644 --- a/src/java/org/apache/lucene/search/spans/SpanWeight.java +++ b/src/java/org/apache/lucene/search/spans/SpanWeight.java @@ -29,7 +29,7 @@ import java.util.Set; /** * Expert-only. Public for use by other weight implementations */ -public class SpanWeight implements Weight { +public class SpanWeight extends QueryWeight { protected Similarity similarity; protected float value; protected float idf; @@ -63,10 +63,9 @@ public class SpanWeight implements Weight { value = queryWeight * idf; // idf for document } - public Scorer scorer(IndexReader reader) throws IOException { - return new SpanScorer(query.getSpans(reader), this, - similarity, - reader.norms(query.getField())); + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) throws IOException { + return new SpanScorer(query.getSpans(reader), this, similarity, reader + .norms(query.getField())); } public Explanation explain(IndexReader reader, int doc) @@ -115,7 +114,7 @@ public class SpanWeight implements Weight { fieldExpl.setDescription("fieldWeight("+field+":"+query.toString(field)+ " in "+doc+"), product of:"); - Explanation tfExpl = scorer(reader).explain(doc); + Explanation tfExpl = scorer(reader, true, false).explain(doc); fieldExpl.addDetail(tfExpl); fieldExpl.addDetail(idfExpl); diff --git a/src/test/org/apache/lucene/index/TestIndexReaderReopen.java b/src/test/org/apache/lucene/index/TestIndexReaderReopen.java index b836a5770b8..86d8f32db88 100644 --- a/src/test/org/apache/lucene/index/TestIndexReaderReopen.java +++ b/src/test/org/apache/lucene/index/TestIndexReaderReopen.java @@ -1073,7 +1073,6 @@ public class TestIndexReaderReopen extends LuceneTestCase { protected void setUp() throws Exception { - // TODO Auto-generated method stub super.setUp(); String tempDir = System.getProperty("java.io.tmpdir"); if (tempDir == null) diff --git a/src/test/org/apache/lucene/index/TestOmitTf.java b/src/test/org/apache/lucene/index/TestOmitTf.java index 1603ab60f60..c8af3a6c05b 100644 --- a/src/test/org/apache/lucene/index/TestOmitTf.java +++ b/src/test/org/apache/lucene/index/TestOmitTf.java @@ -384,5 +384,8 @@ public class TestOmitTf extends LuceneTestCase { public void setNextReader(IndexReader reader, int docBase) { this.docBase = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } } } diff --git a/src/test/org/apache/lucene/search/CheckHits.java b/src/test/org/apache/lucene/search/CheckHits.java index 2ddfca70f2a..cf7d7338f20 100644 --- a/src/test/org/apache/lucene/search/CheckHits.java +++ b/src/test/org/apache/lucene/search/CheckHits.java @@ -17,15 +17,15 @@ package org.apache.lucene.search; * limitations under the License. */ -import org.apache.lucene.store.Directory; -import org.apache.lucene.index.IndexReader; - -import junit.framework.TestCase; - import java.io.IOException; import java.util.Set; import java.util.TreeSet; +import junit.framework.Assert; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.store.Directory; + public class CheckHits { /** @@ -55,9 +55,9 @@ public class CheckHits { if (ignore.contains(new Integer(doc))) continue; Explanation exp = searcher.explain(q, doc); - TestCase.assertNotNull("Explanation of [["+d+"]] for #"+doc+" is null", + Assert.assertNotNull("Explanation of [["+d+"]] for #"+doc+" is null", exp); - TestCase.assertEquals("Explanation of [["+d+"]] for #"+doc+ + Assert.assertEquals("Explanation of [["+d+"]] for #"+doc+ " doesn't indicate non-match: " + exp.toString(), 0.0f, exp.getValue(), 0.0f); } @@ -95,12 +95,14 @@ public class CheckHits { public void collect(int doc) { actual.add(new Integer(doc + base)); } - public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); - TestCase.assertEquals(query.toString(defaultFieldName), correct, actual); + Assert.assertEquals(query.toString(defaultFieldName), correct, actual); QueryUtils.check(query,searcher); } @@ -126,7 +128,7 @@ public class CheckHits { int[] results) throws IOException { if (searcher instanceof IndexSearcher) { - QueryUtils.check(query,(IndexSearcher)searcher); + QueryUtils.check(query,searcher); } ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs; @@ -141,7 +143,7 @@ public class CheckHits { actual.add(new Integer(hits[i].doc)); } - TestCase.assertEquals(query.toString(defaultFieldName), correct, actual); + Assert.assertEquals(query.toString(defaultFieldName), correct, actual); QueryUtils.check(query,searcher); } @@ -149,9 +151,9 @@ public class CheckHits { /** Tests that a Hits has an expected order of documents */ public static void checkDocIds(String mes, int[] results, ScoreDoc[] hits) throws IOException { - TestCase.assertEquals(mes + " nr of hits", hits.length, results.length); + Assert.assertEquals(mes + " nr of hits", hits.length, results.length); for (int i = 0; i < results.length; i++) { - TestCase.assertEquals(mes + " doc nrs for hit " + i, results[i], hits[i].doc); + Assert.assertEquals(mes + " doc nrs for hit " + i, results[i], hits[i].doc); } } @@ -173,11 +175,11 @@ public class CheckHits { public static void checkEqual(Query query, ScoreDoc[] hits1, ScoreDoc[] hits2) throws IOException { final float scoreTolerance = 1.0e-6f; if (hits1.length != hits2.length) { - TestCase.fail("Unequal lengths: hits1="+hits1.length+",hits2="+hits2.length); + Assert.fail("Unequal lengths: hits1="+hits1.length+",hits2="+hits2.length); } for (int i = 0; i < hits1.length; i++) { if (hits1[i].doc != hits2[i].doc) { - TestCase.fail("Hit " + i + " docnumbers don't match\n" + Assert.fail("Hit " + i + " docnumbers don't match\n" + hits2str(hits1, hits2,0,0) + "for query:" + query.toString()); } @@ -185,7 +187,7 @@ public class CheckHits { if ((hits1[i].doc != hits2[i].doc) || Math.abs(hits1[i].score - hits2[i].score) > scoreTolerance) { - TestCase.fail("Hit " + i + ", doc nrs " + hits1[i].doc + " and " + hits2[i].doc + Assert.fail("Hit " + i + ", doc nrs " + hits1[i].doc + " and " + hits2[i].doc + "\nunequal : " + hits1[i].score + "\n and: " + hits2[i].score + "\nfor query:" + query.toString()); @@ -294,7 +296,7 @@ public class CheckHits { boolean deep, Explanation expl) { float value = expl.getValue(); - TestCase.assertEquals(q+": score(doc="+doc+")="+score+ + Assert.assertEquals(q+": score(doc="+doc+")="+score+ " != explanationScore="+value+" Explanation: "+expl, score,value,EXPLAIN_SCORE_TOLERANCE_DELTA); @@ -331,7 +333,7 @@ public class CheckHits { } } } - TestCase.assertTrue( + Assert.assertTrue( q+": multi valued explanation description=\""+descr +"\" must be 'max of plus x times others' or end with 'product of'" +" or 'sum of:' or 'max of:' - "+expl, @@ -356,9 +358,9 @@ public class CheckHits { } else if (maxTimesOthers) { combined = max + x * (sum - max); } else { - TestCase.assertTrue("should never get here!",false); + Assert.assertTrue("should never get here!",false); } - TestCase.assertEquals(q+": actual subDetails combined=="+combined+ + Assert.assertEquals(q+": actual subDetails combined=="+combined+ " != value="+value+" Explanation: "+expl, combined,value,EXPLAIN_SCORE_TOLERANCE_DELTA); } @@ -466,14 +468,15 @@ public class CheckHits { ("exception in hitcollector of [["+d+"]] for #"+doc, e); } - TestCase.assertNotNull("Explanation of [["+d+"]] for #"+doc+" is null", - exp); + Assert.assertNotNull("Explanation of [["+d+"]] for #"+doc+" is null", exp); verifyExplanation(d,doc,scorer.score(),deep,exp); } public void setNextReader(IndexReader reader, int docBase) { base = docBase; } - + public boolean acceptsDocsOutOfOrder() { + return true; + } } } diff --git a/src/test/org/apache/lucene/search/JustCompileSearch.java b/src/test/org/apache/lucene/search/JustCompileSearch.java index 996a090c8cb..896ccb41b2b 100644 --- a/src/test/org/apache/lucene/search/JustCompileSearch.java +++ b/src/test/org/apache/lucene/search/JustCompileSearch.java @@ -38,8 +38,12 @@ final class JustCompileSearch { private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !"; - static final class JustCompileSearchable implements Searchable { + static final class JustCompileSearcher extends Searcher { + protected QueryWeight createQueryWeight(Query query) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + public void close() throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } @@ -48,68 +52,49 @@ final class JustCompileSearch { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public Document doc(int n, FieldSelector fieldSelector) - throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int docFreq(Term term) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - public int[] docFreqs(Term[] terms) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public Explanation explain(Weight weight, int doc) throws IOException { + public Explanation explain(Query query, int doc) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public int maxDoc() throws IOException { + public Similarity getSimilarity() { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public Query rewrite(Query query) throws IOException { + public void search(Query query, Collector results) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public void search(Weight weight, Filter filter, HitCollector results) + public void search(Query query, Filter filter, Collector results) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public void search(Weight weight, Filter filter, Collector collector) + public TopDocs search(Query query, Filter filter, int n) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public TopFieldDocs search(Query query, Filter filter, int n, Sort sort) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - - public TopDocs search(Weight weight, Filter filter, int n) - throws IOException { + + public TopDocs search(Query query, int n) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - - public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) - throws IOException { + + public void setSimilarity(Similarity similarity) { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - - } - - static final class JustCompileSearcher extends Searcher { - - public void close() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Document doc(int i) throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - + public int docFreq(Term term) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public Explanation explain(Weight weight, int doc) throws IOException { + public Explanation explain(QueryWeight weight, int doc) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } @@ -121,22 +106,17 @@ final class JustCompileSearch { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public void search(Weight weight, Filter filter, HitCollector results) + public void search(QueryWeight weight, Filter filter, Collector results) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public void search(Weight weight, Filter filter, Collector results) + public TopDocs search(QueryWeight weight, Filter filter, int n) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } - public TopDocs search(Weight weight, Filter filter, int n) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) + public TopFieldDocs search(QueryWeight weight, Filter filter, int n, Sort sort) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } @@ -163,6 +143,10 @@ final class JustCompileSearch { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } + public boolean acceptsDocsOutOfOrder() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + } static final class JustCompileDocIdSet extends DocIdSet { @@ -316,7 +300,7 @@ final class JustCompileSearch { static final class JustCompilePhraseScorer extends PhraseScorer { - JustCompilePhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, + JustCompilePhraseScorer(QueryWeight weight, TermPositions[] tps, int[] offsets, Similarity similarity, byte[] norms) { super(weight, tps, offsets, similarity, norms); } @@ -437,9 +421,13 @@ final class JustCompileSearch { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } + public boolean acceptsDocsOutOfOrder() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + } - static final class JustCompileWeight implements Weight { + static final class JustCompileWeight extends QueryWeight { public Explanation explain(IndexReader reader, int doc) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); @@ -457,6 +445,7 @@ final class JustCompileSearch { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } + /** @deprecated delete in 3.0 */ public Scorer scorer(IndexReader reader) throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } @@ -464,6 +453,11 @@ final class JustCompileSearch { public float sumOfSquaredWeights() throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } + + public Scorer scorer(IndexReader reader, boolean scoreDocsInOrder, boolean topScorer) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } } diff --git a/src/test/org/apache/lucene/search/QueryUtils.java b/src/test/org/apache/lucene/search/QueryUtils.java index 47a352eef97..0e8fdf91d4d 100644 --- a/src/test/org/apache/lucene/search/QueryUtils.java +++ b/src/test/org/apache/lucene/search/QueryUtils.java @@ -105,7 +105,7 @@ public class QueryUtils { * @throws IOException if serialization check fail. */ private static void checkSerialization(Query q, Searcher s) throws IOException { - Weight w = q.weight(s); + QueryWeight w = q.queryWeight(s); try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); @@ -150,8 +150,8 @@ public class QueryUtils { //System.out.print("Order:");for (int i = 0; i < order.length; i++) System.out.print(order[i]==skip_op ? " skip()":" next()"); System.out.println(); final int opidx[] = {0}; - final Weight w = q.weight(s); - final Scorer scorer = w.scorer(s.getIndexReader()); + final QueryWeight w = q.queryWeight(s); + final Scorer scorer = w.scorer(s.getIndexReader(), true, false); // FUTURE: ensure scorer.doc()==-1 @@ -200,6 +200,9 @@ public class QueryUtils { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); // make sure next call to scorer is false. @@ -228,8 +231,8 @@ public class QueryUtils { float score = scorer.score(); try { for (int i=lastDoc[0]+1; i<=doc; i++) { - Weight w = q.weight(s); - Scorer scorer = w.scorer(s.getIndexReader()); + QueryWeight w = q.queryWeight(s); + Scorer scorer = w.scorer(s.getIndexReader(), true, false); Assert.assertTrue("query collected "+doc+" but skipTo("+i+") says no more docs!",scorer.advance(i) != DocIdSetIterator.NO_MORE_DOCS); Assert.assertEquals("query collected "+doc+" but skipTo("+i+") got to "+scorer.docID(),doc,scorer.docID()); float skipToScore = scorer.score(); @@ -244,9 +247,12 @@ public class QueryUtils { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return false; + } }); - Weight w = q.weight(s); - Scorer scorer = w.scorer(s.getIndexReader()); + QueryWeight w = q.queryWeight(s); + Scorer scorer = w.scorer(s.getIndexReader(), true, false); boolean more = scorer.advance(lastDoc[0] + 1) != DocIdSetIterator.NO_MORE_DOCS; if (more) Assert.assertFalse("query's last doc was "+lastDoc[0]+" but skipTo("+(lastDoc[0]+1)+") got to "+scorer.docID(),more); diff --git a/src/test/org/apache/lucene/search/TestCustomSearcherSort.java b/src/test/org/apache/lucene/search/TestCustomSearcherSort.java index 02349923f64..2daed659e3c 100644 --- a/src/test/org/apache/lucene/search/TestCustomSearcherSort.java +++ b/src/test/org/apache/lucene/search/TestCustomSearcherSort.java @@ -122,9 +122,8 @@ implements Serializable { new SortField("publicationDate_"), SortField.FIELD_SCORE }); - Searcher searcher = - new MultiSearcher(new Searchable[] { - new CustomSearcher (index, 2)}); + Searcher searcher = new MultiSearcher(new Searcher[] { new CustomSearcher( + index, 2) }); // search and check hits matchHits(searcher, custSort); } diff --git a/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java b/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java index 3b19c00c1dc..ce985cee6d8 100644 --- a/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java +++ b/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java @@ -134,8 +134,8 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase{ QueryUtils.check(dq,s); - final Weight dw = dq.weight(s); - final Scorer ds = dw.scorer(r); + final QueryWeight dw = dq.queryWeight(s); + final Scorer ds = dw.scorer(r, true, false); final boolean skipOk = ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS; if (skipOk) { fail("firsttime skipTo found a match? ... " + r.document(ds.docID()).get("id")); @@ -149,40 +149,37 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase{ QueryUtils.check(dq,s); - final Weight dw = dq.weight(s); - final Scorer ds = dw.scorer(r); + final QueryWeight dw = dq.queryWeight(s); + final Scorer ds = dw.scorer(r, true, false); assertTrue("firsttime skipTo found no match", ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS); assertEquals("found wrong docid", "d4", r.document(ds.docID()).get("id")); } + public void testSimpleEqualScores1() throws Exception { + DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); + q.add(tq("hed","albino")); + q.add(tq("hed","elephant")); + QueryUtils.check(q,s); - public void testSimpleEqualScores1() throws Exception { - - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); - q.add(tq("hed","albino")); - q.add(tq("hed","elephant")); - QueryUtils.check(q,s); - - ScoreDoc[] h = s.search(q, null, 1000).scoreDocs; - - try { - assertEquals("all docs should match " + q.toString(), - 4, h.length); - - float score = h[0].score; - for (int i = 1; i < h.length; i++) { - assertEquals("score #" + i + " is not the same", - score, h[i].score, SCORE_COMP_THRESH); - } - } catch (Error e) { - printHits("testSimpleEqualScores1",h,s); - throw e; - } + ScoreDoc[] h = s.search(q, null, 1000).scoreDocs; + try { + assertEquals("all docs should match " + q.toString(), + 4, h.length); + float score = h[0].score; + for (int i = 1; i < h.length; i++) { + assertEquals("score #" + i + " is not the same", + score, h[i].score, SCORE_COMP_THRESH); + } + } catch (Error e) { + printHits("testSimpleEqualScores1",h,s); + throw e; } + } + public void testSimpleEqualScores2() throws Exception { DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); diff --git a/src/test/org/apache/lucene/search/TestDocBoost.java b/src/test/org/apache/lucene/search/TestDocBoost.java index a0e2196c66f..c4bde416b1c 100644 --- a/src/test/org/apache/lucene/search/TestDocBoost.java +++ b/src/test/org/apache/lucene/search/TestDocBoost.java @@ -80,6 +80,9 @@ public class TestDocBoost extends LuceneTestCase { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); float lastScore = 0.0f; diff --git a/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java b/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java index e1d14a0a4be..182b5b52ef4 100644 --- a/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java +++ b/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java @@ -180,6 +180,9 @@ public class TestMultiTermConstantScore extends BaseTestRangeFilter { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); // diff --git a/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java b/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java index 211ab3f1b4e..36a99b06018 100644 --- a/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java +++ b/src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java @@ -99,6 +99,10 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase { this.scorer = new ScoreCachingWrappingScorer(scorer); } + public boolean acceptsDocsOutOfOrder() { + return true; + } + } private static final float[] scores = new float[] { 0.7767749f, 1.7839992f, diff --git a/src/test/org/apache/lucene/search/TestScorerPerf.java b/src/test/org/apache/lucene/search/TestScorerPerf.java index f898b31d2b6..513a01fd5ad 100755 --- a/src/test/org/apache/lucene/search/TestScorerPerf.java +++ b/src/test/org/apache/lucene/search/TestScorerPerf.java @@ -114,6 +114,9 @@ public class TestScorerPerf extends LuceneTestCase { public void setNextReader(IndexReader reader, int base) { docBase = base; } + public boolean acceptsDocsOutOfOrder() { + return true; + } } diff --git a/src/test/org/apache/lucene/search/TestSetNorm.java b/src/test/org/apache/lucene/search/TestSetNorm.java index 7031ff445a6..5417fb84813 100644 --- a/src/test/org/apache/lucene/search/TestSetNorm.java +++ b/src/test/org/apache/lucene/search/TestSetNorm.java @@ -76,6 +76,9 @@ public class TestSetNorm extends LuceneTestCase { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); float lastScore = 0.0f; diff --git a/src/test/org/apache/lucene/search/TestSimilarity.java b/src/test/org/apache/lucene/search/TestSimilarity.java index 165bfdd2944..6f2f59861ae 100644 --- a/src/test/org/apache/lucene/search/TestSimilarity.java +++ b/src/test/org/apache/lucene/search/TestSimilarity.java @@ -74,9 +74,7 @@ public class TestSimilarity extends LuceneTestCase { Term b = new Term("field", "b"); Term c = new Term("field", "c"); - searcher.search - (new TermQuery(b), - new Collector() { + searcher.search(new TermQuery(b), new Collector() { private Scorer scorer; public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; @@ -85,15 +83,16 @@ public class TestSimilarity extends LuceneTestCase { assertTrue(scorer.score() == 1.0f); } public void setNextReader(IndexReader reader, int docBase) {} + public boolean acceptsDocsOutOfOrder() { + return true; + } }); BooleanQuery bq = new BooleanQuery(); bq.add(new TermQuery(a), BooleanClause.Occur.SHOULD); bq.add(new TermQuery(b), BooleanClause.Occur.SHOULD); //System.out.println(bq.toString("field")); - searcher.search - (bq, - new Collector() { + searcher.search(bq, new Collector() { private int base = 0; private Scorer scorer; public void setScorer(Scorer scorer) throws IOException { @@ -106,6 +105,9 @@ public class TestSimilarity extends LuceneTestCase { public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); PhraseQuery pq = new PhraseQuery(); @@ -124,13 +126,14 @@ public class TestSimilarity extends LuceneTestCase { assertTrue(scorer.score() == 1.0f); } public void setNextReader(IndexReader reader, int docBase) {} + public boolean acceptsDocsOutOfOrder() { + return true; + } }); pq.setSlop(2); //System.out.println(pq.toString("field")); - searcher.search - (pq, - new Collector() { + searcher.search(pq, new Collector() { private Scorer scorer; public void setScorer(Scorer scorer) throws IOException { this.scorer = scorer; @@ -140,6 +143,9 @@ public class TestSimilarity extends LuceneTestCase { assertTrue(scorer.score() == 2.0f); } public void setNextReader(IndexReader reader, int docBase) {} + public boolean acceptsDocsOutOfOrder() { + return true; + } }); } } diff --git a/src/test/org/apache/lucene/search/TestTermScorer.java b/src/test/org/apache/lucene/search/TestTermScorer.java index f3fe72bedd2..db12b2d01a5 100644 --- a/src/test/org/apache/lucene/search/TestTermScorer.java +++ b/src/test/org/apache/lucene/search/TestTermScorer.java @@ -70,7 +70,7 @@ public class TestTermScorer extends LuceneTestCase Term allTerm = new Term(FIELD, "all"); TermQuery termQuery = new TermQuery(allTerm); - Weight weight = termQuery.weight(indexSearcher); + QueryWeight weight = termQuery.queryWeight(indexSearcher); TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), @@ -98,6 +98,9 @@ public class TestTermScorer extends LuceneTestCase public void setNextReader(IndexReader reader, int docBase) { base = docBase; } + public boolean acceptsDocsOutOfOrder() { + return true; + } }); assertTrue("docs Size: " + docs.size() + " is not: " + 2, docs.size() == 2); TestHit doc0 = (TestHit) docs.get(0); @@ -129,7 +132,7 @@ public class TestTermScorer extends LuceneTestCase Term allTerm = new Term(FIELD, "all"); TermQuery termQuery = new TermQuery(allTerm); - Weight weight = termQuery.weight(indexSearcher); + QueryWeight weight = termQuery.queryWeight(indexSearcher); TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), @@ -146,14 +149,14 @@ public class TestTermScorer extends LuceneTestCase Term allTerm = new Term(FIELD, "all"); TermQuery termQuery = new TermQuery(allTerm); - Weight weight = termQuery.weight(indexSearcher); + QueryWeight weight = termQuery.queryWeight(indexSearcher); TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), indexReader.norms(FIELD)); assertTrue("Didn't skip", ts.advance(3) != DocIdSetIterator.NO_MORE_DOCS); //The next doc should be doc 5 - assertTrue("doc should be number 5", ts.doc() == 5); + assertTrue("doc should be number 5", ts.docID() == 5); } public void testExplain() throws Exception @@ -161,7 +164,7 @@ public class TestTermScorer extends LuceneTestCase Term allTerm = new Term(FIELD, "all"); TermQuery termQuery = new TermQuery(allTerm); - Weight weight = termQuery.weight(indexSearcher); + QueryWeight weight = termQuery.queryWeight(indexSearcher); TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), @@ -179,7 +182,7 @@ public class TestTermScorer extends LuceneTestCase Term dogsTerm = new Term(FIELD, "dogs"); termQuery = new TermQuery(dogsTerm); - weight = termQuery.weight(indexSearcher); + weight = termQuery.queryWeight(indexSearcher); ts = new TermScorer(weight, indexReader.termDocs(dogsTerm), indexSearcher.getSimilarity(), indexReader.norms(FIELD)); diff --git a/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java b/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java index 4f28708ff58..834e400d215 100644 --- a/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java +++ b/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java @@ -332,6 +332,10 @@ public class TestTimeLimitingCollector extends LuceneTestCase { docBase = base; } + public boolean acceptsDocsOutOfOrder() { + return false; + } + } } diff --git a/src/test/org/apache/lucene/search/TestTopDocsCollector.java b/src/test/org/apache/lucene/search/TestTopDocsCollector.java index e6c04501804..624f725dd36 100644 --- a/src/test/org/apache/lucene/search/TestTopDocsCollector.java +++ b/src/test/org/apache/lucene/search/TestTopDocsCollector.java @@ -69,6 +69,10 @@ public class TestTopDocsCollector extends LuceneTestCase { // Don't do anything. Assign scores in random } + public boolean acceptsDocsOutOfOrder() { + return true; + } + } // Scores array to be used by MyTopDocsCollector. If it is changed, MAX_SCORE diff --git a/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java b/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java index b55dda57c0e..38e2fe3aff2 100644 --- a/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java +++ b/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.Collection; import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.QueryWeight; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.Weight; @@ -69,6 +70,7 @@ final class JustCompileSearchSpans { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } + /** @deprecated delete in 3.0. */ public Collection getTerms() { throw new UnsupportedOperationException(UNSUPPORTED_MSG); } @@ -113,10 +115,16 @@ final class JustCompileSearchSpans { static final class JustCompileSpanScorer extends SpanScorer { + /** @deprecated delete in 3.0 */ protected JustCompileSpanScorer(Spans spans, Weight weight, Similarity similarity, byte[] norms) throws IOException { super(spans, weight, similarity, norms); } + + protected JustCompileSpanScorer(Spans spans, QueryWeight weight, + Similarity similarity, byte[] norms) throws IOException { + super(spans, weight, similarity, norms); + } protected boolean setFreqCurrentDoc() throws IOException { throw new UnsupportedOperationException(UNSUPPORTED_MSG); diff --git a/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java b/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java index 7c927db6ddc..c2e0e6c6831 100644 --- a/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java +++ b/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java @@ -17,23 +17,18 @@ package org.apache.lucene.search.spans; * limitations under the License. */ -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Weight; -import org.apache.lucene.search.CheckHits; -import org.apache.lucene.store.RAMDirectory; - -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.Term; - import org.apache.lucene.analysis.WhitespaceAnalyzer; - import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; - +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.QueryParser; - +import org.apache.lucene.search.CheckHits; +import org.apache.lucene.search.Explanation; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.QueryWeight; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.LuceneTestCase; public class TestNearSpansOrdered extends LuceneTestCase { @@ -163,8 +158,8 @@ public class TestNearSpansOrdered extends LuceneTestCase { */ public void testSpanNearScorerSkipTo1() throws Exception { SpanNearQuery q = makeQuery(); - Weight w = q.createWeight(searcher); - Scorer s = w.scorer(searcher.getIndexReader()); + QueryWeight w = q.queryWeight(searcher); + Scorer s = w.scorer(searcher.getIndexReader(), true, false); assertEquals(1, s.advance(1)); } /** @@ -173,8 +168,8 @@ public class TestNearSpansOrdered extends LuceneTestCase { */ public void testSpanNearScorerExplain() throws Exception { SpanNearQuery q = makeQuery(); - Weight w = q.createWeight(searcher); - Scorer s = w.scorer(searcher.getIndexReader()); + QueryWeight w = q.queryWeight(searcher); + Scorer s = w.scorer(searcher.getIndexReader(), true, false); Explanation e = s.explain(1); assertTrue("Scorer explanation value for doc#1 isn't positive: " + e.toString(),