Index: src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/BooleanQuery.java,v retrieving revision 1.29 diff -u -r1.29 BooleanQuery.java --- src/java/org/apache/lucene/search/BooleanQuery.java 24 Jan 2005 19:21:01 -0000 1.29 +++ src/java/org/apache/lucene/search/BooleanQuery.java 22 Feb 2005 15:14:29 -0000 @@ -17,6 +17,8 @@ */ import java.io.IOException; +import java.util.Iterator; +import java.util.Set; import java.util.Vector; import org.apache.lucene.index.IndexReader; @@ -117,16 +119,16 @@ } private class BooleanWeight implements Weight { - protected Searcher searcher; + protected Similarity similarity; protected Vector weights = new Vector(); - public BooleanWeight(Searcher searcher) { - this.searcher = searcher; + public BooleanWeight(Searcher searcher) + throws IOException { + this.similarity = getSimilarity(searcher); for (int i = 0 ; i < clauses.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); weights.add(c.getQuery().createWeight(searcher)); } - //System.out.println("Creating " + getClass().getName()); } public Query getQuery() { return BooleanQuery.this; } @@ -177,7 +179,7 @@ if (allRequired && noneBoolean) { // ConjunctionScorer is okay ConjunctionScorer result = - new ConjunctionScorer(getSimilarity(searcher)); + new ConjunctionScorer(similarity); for (int i = 0 ; i < weights.size(); i++) { Weight w = (Weight)weights.elementAt(i); Scorer subScorer = w.scorer(reader); @@ -189,7 +191,7 @@ } // Use good-old BooleanScorer instead. - BooleanScorer result = new BooleanScorer(getSimilarity(searcher)); + BooleanScorer result = new BooleanScorer(similarity); for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); @@ -233,7 +235,7 @@ if (coord == 1) // only one clause matched sumExpl = sumExpl.getDetails()[0]; // eliminate wrapper - float coordFactor = getSimilarity(searcher).coord(coord, maxCoord); + float coordFactor = similarity.coord(coord, maxCoord); if (coordFactor == 1.0f) // coord is no-op return sumExpl; // eliminate wrapper else { @@ -250,13 +252,16 @@ private class BooleanWeight2 extends BooleanWeight { /* Merge into BooleanWeight in case the 1.4 BooleanScorer is dropped */ - public BooleanWeight2(Searcher searcher) { super(searcher); } + public BooleanWeight2(Searcher searcher) + throws IOException { + super(searcher); + } /** @return An alternative Scorer that uses and provides skipTo(), * and scores documents in document number order. */ public Scorer scorer(IndexReader reader) throws IOException { - BooleanScorer2 result = new BooleanScorer2(getSimilarity(searcher)); + BooleanScorer2 result = new BooleanScorer2(similarity); for (int i = 0 ; i < weights.size(); i++) { BooleanClause c = (BooleanClause)clauses.elementAt(i); @@ -283,7 +288,7 @@ return useScorer14; } - protected Weight createWeight(Searcher searcher) { + protected Weight createWeight(Searcher searcher) throws IOException { return getUseScorer14() ? (Weight) new BooleanWeight(searcher) : (Weight) new BooleanWeight2(searcher); } @@ -322,7 +327,19 @@ return this; // no clauses rewrote } - + // inherit javadoc + public void extractTerms(Set terms) { + for (Iterator i = clauses.iterator(); i.hasNext();) { + BooleanClause clause = (BooleanClause) i.next(); + clause.getQuery().extractTerms(terms); + } + } + + // inherit javadoc + public Query combine(Query[] queries) { + return Query.mergeBooleanQueries(queries); + } + public Object clone() { BooleanQuery clone = (BooleanQuery)super.clone(); clone.clauses = (Vector)this.clauses.clone(); Index: src/java/org/apache/lucene/search/FilteredQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/FilteredQuery.java,v retrieving revision 1.5 diff -u -r1.5 FilteredQuery.java --- src/java/org/apache/lucene/search/FilteredQuery.java 18 Jun 2004 09:52:25 -0000 1.5 +++ src/java/org/apache/lucene/search/FilteredQuery.java 22 Feb 2005 15:14:29 -0000 @@ -19,6 +19,7 @@ import org.apache.lucene.index.IndexReader; import java.io.IOException; import java.util.BitSet; +import java.util.Set; /** @@ -56,8 +57,9 @@ * 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) { + protected Weight createWeight (final Searcher searcher) throws IOException { final Weight weight = query.createWeight (searcher); + final Similarity similarity = query.getSimilarity(searcher); return new Weight() { // pass these methods through to enclosed query's weight @@ -74,7 +76,7 @@ public Scorer scorer (IndexReader indexReader) throws IOException { final Scorer scorer = weight.scorer (indexReader); final BitSet bitset = filter.bits (indexReader); - return new Scorer (query.getSimilarity (searcher)) { + return new Scorer (similarity) { // pass these methods through to the enclosed scorer public boolean next() throws IOException { return scorer.next(); } @@ -116,6 +118,11 @@ return query; } + // inherit javadoc + public void extractTerms(Set terms) { + getQuery().extractTerms(terms); + } + /** Prints a user-readable version of this query. */ public String toString (String s) { return "filtered("+query.toString(s)+")->"+filter; Index: src/java/org/apache/lucene/search/Hits.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/Hits.java,v retrieving revision 1.12 diff -u -r1.12 Hits.java --- src/java/org/apache/lucene/search/Hits.java 29 Mar 2004 22:48:03 -0000 1.12 +++ src/java/org/apache/lucene/search/Hits.java 22 Feb 2005 15:14:29 -0000 @@ -23,7 +23,7 @@ /** A ranked list of documents, used to hold search results. */ public final class Hits { - private Query query; + private Weight weight; private Searcher searcher; private Filter filter = null; private Sort sort = null; @@ -37,14 +37,14 @@ private int maxDocs = 200; // max to cache Hits(Searcher s, Query q, Filter f) throws IOException { - query = q; + weight = q.weight(s); searcher = s; filter = f; getMoreDocs(50); // retrieve 100 initially } Hits(Searcher s, Query q, Filter f, Sort o) throws IOException { - query = q; + weight = q.weight(s); searcher = s; filter = f; sort = o; @@ -61,7 +61,7 @@ } int n = min * 2; // double # retrieved - TopDocs topDocs = (sort == null) ? searcher.search(query, filter, n) : searcher.search(query, filter, n, sort); + TopDocs topDocs = (sort == null) ? searcher.search(weight, filter, n) : searcher.search(weight, filter, n, sort); length = topDocs.totalHits; ScoreDoc[] scoreDocs = topDocs.scoreDocs; Index: src/java/org/apache/lucene/search/IndexSearcher.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/IndexSearcher.java,v retrieving revision 1.23 diff -u -r1.23 IndexSearcher.java --- src/java/org/apache/lucene/search/IndexSearcher.java 14 Nov 2004 13:26:28 -0000 1.23 +++ src/java/org/apache/lucene/search/IndexSearcher.java 22 Feb 2005 15:14:29 -0000 @@ -83,11 +83,17 @@ // inherit javadoc public TopDocs search(Query query, Filter filter, final int nDocs) throws IOException { + return search(query.weight(this), filter, nDocs); + } + + // inherit javadoc + public TopDocs search(Weight weight, Filter filter, final int nDocs) + throws IOException { if (nDocs <= 0) // null might be returned from hq.top() below. throw new IllegalArgumentException("nDocs must be > 0"); - - Scorer scorer = query.weight(this).scorer(reader); + + Scorer scorer = weight.scorer(reader); if (scorer == null) return new TopDocs(0, new ScoreDoc[0]); @@ -119,7 +125,14 @@ public TopFieldDocs search(Query query, Filter filter, final int nDocs, Sort sort) throws IOException { - Scorer scorer = query.weight(this).scorer(reader); + return search(query.weight(this), filter, nDocs, sort); + } + + // inherit javadoc + public TopFieldDocs search(Weight weight, Filter filter, final int nDocs, + Sort sort) + throws IOException { + Scorer scorer = weight.scorer(reader); if (scorer == null) return new TopFieldDocs(0, new ScoreDoc[0], sort.fields); @@ -148,6 +161,12 @@ // inherit javadoc public void search(Query query, Filter filter, final HitCollector results) throws IOException { + search(query.weight(this), filter, results); + } + + // inherit javadoc + public void search(Weight weight, Filter filter, + final HitCollector results) throws IOException { HitCollector collector = results; if (filter != null) { final BitSet bits = filter.bits(reader); @@ -160,7 +179,7 @@ }; } - Scorer scorer = query.weight(this).scorer(reader); + Scorer scorer = weight.scorer(reader); if (scorer == null) return; scorer.score(collector); @@ -176,7 +195,10 @@ } public Explanation explain(Query query, int doc) throws IOException { - return query.weight(this).explain(reader, doc); + return explain(query.weight(this), doc); } + public Explanation explain(Weight weight, int doc) throws IOException { + return weight.explain(reader, doc); + } } Index: src/java/org/apache/lucene/search/MultiPhraseQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/MultiPhraseQuery.java,v retrieving revision 1.2 diff -u -r1.2 MultiPhraseQuery.java --- src/java/org/apache/lucene/search/MultiPhraseQuery.java 19 Jan 2005 23:32:52 -0000 1.2 +++ src/java/org/apache/lucene/search/MultiPhraseQuery.java 22 Feb 2005 15:14:29 -0000 @@ -107,27 +107,30 @@ } private class MultiPhraseWeight implements Weight { - private Searcher searcher; + private Similarity similarity; private float value; private float idf; private float queryNorm; private float queryWeight; - public MultiPhraseWeight(Searcher searcher) { - this.searcher = searcher; + public MultiPhraseWeight(Searcher searcher) + throws IOException { + this.similarity = getSimilarity(searcher); + + // compute idf + Iterator i = termArrays.iterator(); + while (i.hasNext()) { + Term[] terms = (Term[])i.next(); + for (int j=0; j{@link HitCollector#collect(int,float)} is called for every non-zero - * scoring 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 query to match documents - * @param filter if non-null, a bitset used to eliminate some documents - * @param results to receive hits + /** + * @see org.apache.lucene.search.Searchable#search(Weight, Filter, HitCollector) * * TODO: parallelize this one too */ - public void search(Query query, Filter filter, final HitCollector results) + public void search(Weight weight, Filter filter, final HitCollector results) throws IOException { - for (int i = 0; i < searchables.length; i++) { - - final int start = starts[i]; - - searchables[i].search(query, filter, new HitCollector() { - public void collect(int doc, float score) { - results.collect(doc + start, score); - } - }); - - } + super.search(weight, filter, results); } /* @@ -181,11 +157,7 @@ * @see org.apache.lucene.search.Searchable#rewrite(org.apache.lucene.search.Query) */ public Query rewrite(Query original) throws IOException { - Query[] queries = new Query[searchables.length]; - for (int i = 0; i < searchables.length; i++) { - queries[i] = searchables[i].rewrite(original); - } - return original.combine(queries); + return super.rewrite(original); } } @@ -196,7 +168,7 @@ class MultiSearcherThread extends Thread { private Searchable searchable; - private Query query; + private Weight weight; private Filter filter; private int nDocs; private TopDocs docs; @@ -208,7 +180,7 @@ public MultiSearcherThread( Searchable searchable, - Query query, + Weight weight, Filter filter, int nDocs, HitQueue hq, @@ -217,7 +189,7 @@ String name) { super(name); this.searchable = searchable; - this.query = query; + this.weight = weight; this.filter = filter; this.nDocs = nDocs; this.hq = hq; @@ -227,7 +199,7 @@ public MultiSearcherThread( Searchable searchable, - Query query, + Weight weight, Filter filter, int nDocs, FieldDocSortedHitQueue hq, @@ -237,7 +209,7 @@ String name) { super(name); this.searchable = searchable; - this.query = query; + this.weight = weight; this.filter = filter; this.nDocs = nDocs; this.hq = hq; @@ -248,8 +220,8 @@ public void run() { try { - docs = (sort == null) ? searchable.search (query, filter, nDocs) - : searchable.search (query, filter, nDocs, sort); + docs = (sort == null) ? searchable.search (weight, filter, nDocs) + : searchable.search (weight, filter, nDocs, sort); } // Store the IOException for later use by the caller of this thread catch (IOException ioe) { Index: src/java/org/apache/lucene/search/PhrasePrefixQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/PhrasePrefixQuery.java,v retrieving revision 1.18 diff -u -r1.18 PhrasePrefixQuery.java --- src/java/org/apache/lucene/search/PhrasePrefixQuery.java 10 Oct 2004 15:27:15 -0000 1.18 +++ src/java/org/apache/lucene/search/PhrasePrefixQuery.java 22 Feb 2005 15:14:29 -0000 @@ -108,27 +108,30 @@ } private class PhrasePrefixWeight implements Weight { - private Searcher searcher; + private Similarity similarity; private float value; private float idf; private float queryNorm; private float queryWeight; - public PhrasePrefixWeight(Searcher searcher) { - this.searcher = searcher; + public PhrasePrefixWeight(Searcher searcher) + throws IOException { + this.similarity = getSimilarity(searcher); + + // compute idf + Iterator i = termArrays.iterator(); + while (i.hasNext()) { + Term[] terms = (Term[])i.next(); + for (int j=0; jterm. Returns an array with these + * document frequencies. Used to minimize number of remote calls. + */ + int[] docFreqs(Term[] terms) throws IOException; + /** Expert: Returns one greater than the largest possible document number. * Called by search code to compute term weights. * @see IndexReader#maxDoc() @@ -72,8 +87,16 @@ *

Applications should usually call {@link Searcher#search(Query)} or * {@link Searcher#search(Query,Filter)} instead. * @throws BooleanQuery.TooManyClauses + * + * @deprecated */ TopDocs search(Query query, Filter filter, int n) throws IOException; + + /** Expert: Low-level search implementation. + * Identical to {@link #search(Query, Filter, int)}, but takes + * a Weight instead of a query. + */ + TopDocs search(Weight weight, Filter filter, int n) throws IOException; /** Expert: Returns the stored fields of document i. * Called by {@link HitCollector} implementations. @@ -97,6 +120,12 @@ */ Explanation explain(Query query, int doc) throws IOException; + /** + * Identical to {@link #search(Query, Filter, HitCollector)}, but takes + * a Weight instead of a query. + */ + Explanation explain(Weight weight, int doc) 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 @@ -105,7 +134,16 @@ *

Applications should usually call {@link * Searcher#search(Query,Filter,Sort)} instead. * @throws BooleanQuery.TooManyClauses + * + * @deprecated */ TopFieldDocs search(Query query, Filter filter, int n, Sort sort) throws IOException; + + /** Expert: Low-level search implementation. + * Identical to {@link #search(Query, Filter, int, Sort)}, but takes + * a Weight instead of a query. + */ + TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) + throws IOException; } Index: src/java/org/apache/lucene/search/Searcher.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/Searcher.java,v retrieving revision 1.13 diff -u -r1.13 Searcher.java --- src/java/org/apache/lucene/search/Searcher.java 14 Dec 2004 19:00:01 -0000 1.13 +++ src/java/org/apache/lucene/search/Searcher.java 22 Feb 2005 15:14:30 -0000 @@ -18,6 +18,8 @@ import java.io.IOException; +import org.apache.lucene.index.Term; + /** An abstract base class for search implementations. * Implements some common utility methods. */ @@ -72,7 +74,7 @@ */ public void search(Query query, HitCollector results) throws IOException { - search(query, (Filter)null, results); + search(query.weight(this), (Filter)null, results); } /** The Similarity implementation used by this searcher. */ @@ -93,4 +95,15 @@ public Similarity getSimilarity() { return this.similarity; } + + + // inherit javadoc + public int[] docFreqs(Term[] terms) throws IOException { + int[] result = new int[terms.length]; + for (int i = 0; i < terms.length; i++) { + result[i] = docFreq(terms[i]); + } + return result; + } + } Index: src/java/org/apache/lucene/search/Similarity.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/Similarity.java,v retrieving revision 1.17 diff -u -r1.17 Similarity.java --- src/java/org/apache/lucene/search/Similarity.java 27 Oct 2004 21:59:02 -0000 1.17 +++ src/java/org/apache/lucene/search/Similarity.java 22 Feb 2005 15:14:30 -0000 @@ -17,6 +17,7 @@ */ import java.io.IOException; +import java.io.Serializable; import java.util.Collection; import java.util.Iterator; @@ -84,7 +85,7 @@ * @see IndexWriter#setSimilarity(Similarity) * @see Searcher#setSimilarity(Similarity) */ -public abstract class Similarity { +public abstract class Similarity implements Serializable { /** The Similarity implementation used by default. */ private static Similarity defaultImpl = new DefaultSimilarity(); Index: src/java/org/apache/lucene/search/TermQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/TermQuery.java,v retrieving revision 1.13 diff -u -r1.13 TermQuery.java --- src/java/org/apache/lucene/search/TermQuery.java 6 Sep 2004 22:09:13 -0000 1.13 +++ src/java/org/apache/lucene/search/TermQuery.java 22 Feb 2005 15:14:30 -0000 @@ -17,6 +17,8 @@ */ import java.io.IOException; +import java.util.Set; + import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; import org.apache.lucene.index.IndexReader; @@ -28,14 +30,16 @@ private Term term; private class TermWeight implements Weight { - private Searcher searcher; + private Similarity similarity; private float value; private float idf; private float queryNorm; private float queryWeight; - public TermWeight(Searcher searcher) { - this.searcher = searcher; + public TermWeight(Searcher searcher) + throws IOException { + this.similarity = getSimilarity(searcher); + idf = getSimilarity(searcher).idf(term, searcher); // compute idf } public String toString() { return "weight(" + TermQuery.this + ")"; } @@ -44,7 +48,6 @@ public float getValue() { return value; } public float sumOfSquaredWeights() throws IOException { - idf = getSimilarity(searcher).idf(term, searcher); // compute idf queryWeight = idf * getBoost(); // compute query weight return queryWeight * queryWeight; // square it } @@ -61,7 +64,7 @@ if (termDocs == null) return null; - return new TermScorer(this, termDocs, getSimilarity(searcher), + return new TermScorer(this, termDocs, similarity, reader.norms(term.field())); } @@ -72,7 +75,7 @@ result.setDescription("weight("+getQuery()+" in "+doc+"), product of:"); Explanation idfExpl = - new Explanation(idf, "idf(docFreq=" + searcher.docFreq(term) + ")"); + new Explanation(idf, "idf(docFreq=" + reader.docFreq(term) + ")"); // explain query weight Explanation queryExpl = new Explanation(); @@ -134,9 +137,13 @@ /** Returns the term of this query. */ public Term getTerm() { return term; } - protected Weight createWeight(Searcher searcher) { + protected Weight createWeight(Searcher searcher) throws IOException { return new TermWeight(searcher); } + + public void extractTerms(Set terms) { + terms.add(getTerm()); + } /** Prints a user-readable version of this query. */ public String toString(String field) { Index: src/java/org/apache/lucene/search/spans/SpanQuery.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/spans/SpanQuery.java,v retrieving revision 1.2 diff -u -r1.2 SpanQuery.java --- src/java/org/apache/lucene/search/spans/SpanQuery.java 2 Feb 2004 13:27:52 -0000 1.2 +++ src/java/org/apache/lucene/search/spans/SpanQuery.java 22 Feb 2005 15:14:30 -0000 @@ -37,7 +37,7 @@ /** Returns a collection of all terms matched by this query.*/ public abstract Collection getTerms(); - protected Weight createWeight(Searcher searcher) { + protected Weight createWeight(Searcher searcher) throws IOException { return new SpanWeight(this, searcher); } Index: src/java/org/apache/lucene/search/spans/SpanWeight.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/search/spans/SpanWeight.java,v retrieving revision 1.3 diff -u -r1.3 SpanWeight.java --- src/java/org/apache/lucene/search/spans/SpanWeight.java 6 Feb 2004 19:19:20 -0000 1.3 +++ src/java/org/apache/lucene/search/spans/SpanWeight.java 22 Feb 2005 15:14:30 -0000 @@ -32,7 +32,7 @@ import org.apache.lucene.search.Similarity; class SpanWeight implements Weight { - private Searcher searcher; + private Similarity similarity; private float value; private float idf; private float queryNorm; @@ -41,17 +41,19 @@ private Collection terms; private SpanQuery query; - public SpanWeight(SpanQuery query, Searcher searcher) { - this.searcher = searcher; + public SpanWeight(SpanQuery query, Searcher searcher) + throws IOException { + this.similarity = query.getSimilarity(searcher); this.query = query; this.terms = query.getTerms(); + + idf = this.query.getSimilarity(searcher).idf(terms, searcher); } public Query getQuery() { return query; } public float getValue() { return value; } public float sumOfSquaredWeights() throws IOException { - idf = this.query.getSimilarity(searcher).idf(terms, searcher); queryWeight = idf * query.getBoost(); // compute query weight return queryWeight * queryWeight; // square it } @@ -64,7 +66,7 @@ public Scorer scorer(IndexReader reader) throws IOException { return new SpanScorer(query.getSpans(reader), this, - query.getSimilarity(searcher), + similarity, reader.norms(query.getField())); } @@ -81,7 +83,7 @@ Term term = (Term)i.next(); docFreqs.append(term.text()); docFreqs.append("="); - docFreqs.append(searcher.docFreq(term)); + docFreqs.append(reader.docFreq(term)); if (i.hasNext()) { docFreqs.append(" "); Index: src/test/org/apache/lucene/search/TestSort.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/test/org/apache/lucene/search/TestSort.java,v retrieving revision 1.8 diff -u -r1.8 TestSort.java --- src/test/org/apache/lucene/search/TestSort.java 30 Aug 2004 20:52:15 -0000 1.8 +++ src/test/org/apache/lucene/search/TestSort.java 22 Feb 2005 15:14:30 -0000 @@ -344,12 +344,9 @@ HashMap scoresA = getScores (full.search (queryA)); // we'll test searching locally, remote and multi - // note: the multi test depends on each separate index containing - // the same documents as our local index, so the computed normalization - // will be the same. so we make a multi searcher over two equal document - // sets - not realistic, but necessary for testing. MultiSearcher remote = new MultiSearcher (new Searchable[] { getRemote() }); - MultiSearcher multi = new MultiSearcher (new Searchable[] { full, full }); + // multi is not really multi, but tests the MultiSearcher handling + MultiSearcher multi = new MultiSearcher (new Searchable[] { full }); // change sorting and make sure relevancy stays the same