mirror of https://github.com/apache/lucene.git
- Applied Chuck's and Wolf's patch for bug 31841
http://issues.apache.org/bugzilla/show_bug.cgi?id=31841 git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@162008 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bc1a7b0f6f
commit
e4bd715106
|
@ -21,7 +21,13 @@ Changes in runtime behavior
|
||||||
and WildcardQueries before). Use setLowercaseExpandedTerms(false)
|
and WildcardQueries before). Use setLowercaseExpandedTerms(false)
|
||||||
to disable that behavior but note that this also affects
|
to disable that behavior but note that this also affects
|
||||||
PrefixQueries and WildcardQueries. (Daniel Naber)
|
PrefixQueries and WildcardQueries. (Daniel Naber)
|
||||||
|
|
||||||
|
4. Document frequency that is computed when MultiSearcher is used is now
|
||||||
|
computed correctly and "globally" across subsearchers and indices, while
|
||||||
|
before it used to be computed locally to each index, which caused
|
||||||
|
ranking across multiple indices not to be equivalent.
|
||||||
|
(Chuck Williams, Wolf Siberski via Otis)
|
||||||
|
|
||||||
New features
|
New features
|
||||||
|
|
||||||
1. Added support for stored compressed fields (patch #31149)
|
1. Added support for stored compressed fields (patch #31149)
|
||||||
|
|
|
@ -17,6 +17,8 @@ package org.apache.lucene.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@ -153,16 +155,16 @@ public class BooleanQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BooleanWeight implements Weight {
|
private class BooleanWeight implements Weight {
|
||||||
protected Searcher searcher;
|
protected Similarity similarity;
|
||||||
protected Vector weights = new Vector();
|
protected Vector weights = new Vector();
|
||||||
|
|
||||||
public BooleanWeight(Searcher searcher) {
|
public BooleanWeight(Searcher searcher)
|
||||||
this.searcher = searcher;
|
throws IOException {
|
||||||
|
this.similarity = getSimilarity(searcher);
|
||||||
for (int i = 0 ; i < clauses.size(); i++) {
|
for (int i = 0 ; i < clauses.size(); i++) {
|
||||||
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
||||||
weights.add(c.getQuery().createWeight(searcher));
|
weights.add(c.getQuery().createWeight(searcher));
|
||||||
}
|
}
|
||||||
//System.out.println("Creating " + getClass().getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query getQuery() { return BooleanQuery.this; }
|
public Query getQuery() { return BooleanQuery.this; }
|
||||||
|
@ -213,7 +215,7 @@ public class BooleanQuery extends Query {
|
||||||
|
|
||||||
if (allRequired && noneBoolean) { // ConjunctionScorer is okay
|
if (allRequired && noneBoolean) { // ConjunctionScorer is okay
|
||||||
ConjunctionScorer result =
|
ConjunctionScorer result =
|
||||||
new ConjunctionScorer(getSimilarity(searcher));
|
new ConjunctionScorer(similarity);
|
||||||
for (int i = 0 ; i < weights.size(); i++) {
|
for (int i = 0 ; i < weights.size(); i++) {
|
||||||
Weight w = (Weight)weights.elementAt(i);
|
Weight w = (Weight)weights.elementAt(i);
|
||||||
Scorer subScorer = w.scorer(reader);
|
Scorer subScorer = w.scorer(reader);
|
||||||
|
@ -225,7 +227,7 @@ public class BooleanQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use good-old BooleanScorer instead.
|
// Use good-old BooleanScorer instead.
|
||||||
BooleanScorer result = new BooleanScorer(getSimilarity(searcher));
|
BooleanScorer result = new BooleanScorer(similarity);
|
||||||
|
|
||||||
for (int i = 0 ; i < weights.size(); i++) {
|
for (int i = 0 ; i < weights.size(); i++) {
|
||||||
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
||||||
|
@ -269,7 +271,7 @@ public class BooleanQuery extends Query {
|
||||||
if (coord == 1) // only one clause matched
|
if (coord == 1) // only one clause matched
|
||||||
sumExpl = sumExpl.getDetails()[0]; // eliminate wrapper
|
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
|
if (coordFactor == 1.0f) // coord is no-op
|
||||||
return sumExpl; // eliminate wrapper
|
return sumExpl; // eliminate wrapper
|
||||||
else {
|
else {
|
||||||
|
@ -286,13 +288,16 @@ public class BooleanQuery extends Query {
|
||||||
|
|
||||||
private class BooleanWeight2 extends BooleanWeight {
|
private class BooleanWeight2 extends BooleanWeight {
|
||||||
/* Merge into BooleanWeight in case the 1.4 BooleanScorer is dropped */
|
/* 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(),
|
/** @return An alternative Scorer that uses and provides skipTo(),
|
||||||
* and scores documents in document number order.
|
* and scores documents in document number order.
|
||||||
*/
|
*/
|
||||||
public Scorer scorer(IndexReader reader) throws IOException {
|
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++) {
|
for (int i = 0 ; i < weights.size(); i++) {
|
||||||
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
BooleanClause c = (BooleanClause)clauses.elementAt(i);
|
||||||
|
@ -319,7 +324,7 @@ public class BooleanQuery extends Query {
|
||||||
return useScorer14;
|
return useScorer14;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
return getUseScorer14() ? (Weight) new BooleanWeight(searcher)
|
return getUseScorer14() ? (Weight) new BooleanWeight(searcher)
|
||||||
: (Weight) new BooleanWeight2(searcher);
|
: (Weight) new BooleanWeight2(searcher);
|
||||||
}
|
}
|
||||||
|
@ -358,6 +363,18 @@ public class BooleanQuery extends Query {
|
||||||
return this; // no clauses rewrote
|
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() {
|
public Object clone() {
|
||||||
BooleanQuery clone = (BooleanQuery)super.clone();
|
BooleanQuery clone = (BooleanQuery)super.clone();
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.lucene.search;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,8 +57,9 @@ extends Query {
|
||||||
* Returns a Weight that applies the filter to the enclosed query's Weight.
|
* Returns a Weight that applies the filter to the enclosed query's Weight.
|
||||||
* This is accomplished by overriding the Scorer returned by the 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 Weight weight = query.createWeight (searcher);
|
||||||
|
final Similarity similarity = query.getSimilarity(searcher);
|
||||||
return new Weight() {
|
return new Weight() {
|
||||||
|
|
||||||
// pass these methods through to enclosed query's weight
|
// pass these methods through to enclosed query's weight
|
||||||
|
@ -74,7 +76,7 @@ extends Query {
|
||||||
public Scorer scorer (IndexReader indexReader) throws IOException {
|
public Scorer scorer (IndexReader indexReader) throws IOException {
|
||||||
final Scorer scorer = weight.scorer (indexReader);
|
final Scorer scorer = weight.scorer (indexReader);
|
||||||
final BitSet bitset = filter.bits (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
|
// pass these methods through to the enclosed scorer
|
||||||
public boolean next() throws IOException { return scorer.next(); }
|
public boolean next() throws IOException { return scorer.next(); }
|
||||||
|
@ -116,6 +118,11 @@ extends Query {
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inherit javadoc
|
||||||
|
public void extractTerms(Set terms) {
|
||||||
|
getQuery().extractTerms(terms);
|
||||||
|
}
|
||||||
|
|
||||||
/** Prints a user-readable version of this query. */
|
/** Prints a user-readable version of this query. */
|
||||||
public String toString (String s) {
|
public String toString (String s) {
|
||||||
return "filtered("+query.toString(s)+")->"+filter;
|
return "filtered("+query.toString(s)+")->"+filter;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.document.Document;
|
||||||
|
|
||||||
/** A ranked list of documents, used to hold search results. */
|
/** A ranked list of documents, used to hold search results. */
|
||||||
public final class Hits {
|
public final class Hits {
|
||||||
private Query query;
|
private Weight weight;
|
||||||
private Searcher searcher;
|
private Searcher searcher;
|
||||||
private Filter filter = null;
|
private Filter filter = null;
|
||||||
private Sort sort = null;
|
private Sort sort = null;
|
||||||
|
@ -37,14 +37,14 @@ public final class Hits {
|
||||||
private int maxDocs = 200; // max to cache
|
private int maxDocs = 200; // max to cache
|
||||||
|
|
||||||
Hits(Searcher s, Query q, Filter f) throws IOException {
|
Hits(Searcher s, Query q, Filter f) throws IOException {
|
||||||
query = q;
|
weight = q.weight(s);
|
||||||
searcher = s;
|
searcher = s;
|
||||||
filter = f;
|
filter = f;
|
||||||
getMoreDocs(50); // retrieve 100 initially
|
getMoreDocs(50); // retrieve 100 initially
|
||||||
}
|
}
|
||||||
|
|
||||||
Hits(Searcher s, Query q, Filter f, Sort o) throws IOException {
|
Hits(Searcher s, Query q, Filter f, Sort o) throws IOException {
|
||||||
query = q;
|
weight = q.weight(s);
|
||||||
searcher = s;
|
searcher = s;
|
||||||
filter = f;
|
filter = f;
|
||||||
sort = o;
|
sort = o;
|
||||||
|
@ -61,7 +61,7 @@ public final class Hits {
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = min * 2; // double # retrieved
|
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;
|
length = topDocs.totalHits;
|
||||||
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
|
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
|
||||||
|
|
||||||
|
|
|
@ -88,11 +88,17 @@ public class IndexSearcher extends Searcher {
|
||||||
// inherit javadoc
|
// inherit javadoc
|
||||||
public TopDocs search(Query query, Filter filter, final int nDocs)
|
public TopDocs search(Query query, Filter filter, final int nDocs)
|
||||||
throws IOException {
|
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.
|
if (nDocs <= 0) // null might be returned from hq.top() below.
|
||||||
throw new IllegalArgumentException("nDocs must be > 0");
|
throw new IllegalArgumentException("nDocs must be > 0");
|
||||||
|
|
||||||
Scorer scorer = query.weight(this).scorer(reader);
|
Scorer scorer = weight.scorer(reader);
|
||||||
if (scorer == null)
|
if (scorer == null)
|
||||||
return new TopDocs(0, new ScoreDoc[0]);
|
return new TopDocs(0, new ScoreDoc[0]);
|
||||||
|
|
||||||
|
@ -124,7 +130,14 @@ public class IndexSearcher extends Searcher {
|
||||||
public TopFieldDocs search(Query query, Filter filter, final int nDocs,
|
public TopFieldDocs search(Query query, Filter filter, final int nDocs,
|
||||||
Sort sort)
|
Sort sort)
|
||||||
throws IOException {
|
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)
|
if (scorer == null)
|
||||||
return new TopFieldDocs(0, new ScoreDoc[0], sort.fields);
|
return new TopFieldDocs(0, new ScoreDoc[0], sort.fields);
|
||||||
|
|
||||||
|
@ -153,6 +166,12 @@ public class IndexSearcher extends Searcher {
|
||||||
// inherit javadoc
|
// inherit javadoc
|
||||||
public void search(Query query, Filter filter,
|
public void search(Query query, Filter filter,
|
||||||
final HitCollector results) throws IOException {
|
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;
|
HitCollector collector = results;
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
final BitSet bits = filter.bits(reader);
|
final BitSet bits = filter.bits(reader);
|
||||||
|
@ -165,7 +184,7 @@ public class IndexSearcher extends Searcher {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Scorer scorer = query.weight(this).scorer(reader);
|
Scorer scorer = weight.scorer(reader);
|
||||||
if (scorer == null)
|
if (scorer == null)
|
||||||
return;
|
return;
|
||||||
scorer.score(collector);
|
scorer.score(collector);
|
||||||
|
@ -181,7 +200,10 @@ public class IndexSearcher extends Searcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Explanation explain(Query query, int doc) throws IOException {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,27 +107,30 @@ public class MultiPhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MultiPhraseWeight implements Weight {
|
private class MultiPhraseWeight implements Weight {
|
||||||
private Searcher searcher;
|
private Similarity similarity;
|
||||||
private float value;
|
private float value;
|
||||||
private float idf;
|
private float idf;
|
||||||
private float queryNorm;
|
private float queryNorm;
|
||||||
private float queryWeight;
|
private float queryWeight;
|
||||||
|
|
||||||
public MultiPhraseWeight(Searcher searcher) {
|
public MultiPhraseWeight(Searcher searcher)
|
||||||
this.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<terms.length; j++) {
|
||||||
|
idf += getSimilarity(searcher).idf(terms[j], searcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query getQuery() { return MultiPhraseQuery.this; }
|
public Query getQuery() { return MultiPhraseQuery.this; }
|
||||||
public float getValue() { return value; }
|
public float getValue() { return value; }
|
||||||
|
|
||||||
public float sumOfSquaredWeights() throws IOException {
|
public float sumOfSquaredWeights() throws IOException {
|
||||||
Iterator i = termArrays.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
Term[] terms = (Term[])i.next();
|
|
||||||
for (int j=0; j<terms.length; j++)
|
|
||||||
idf += getSimilarity(searcher).idf(terms[j], searcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
queryWeight = idf * getBoost(); // compute query weight
|
queryWeight = idf * getBoost(); // compute query weight
|
||||||
return queryWeight * queryWeight; // square it
|
return queryWeight * queryWeight; // square it
|
||||||
}
|
}
|
||||||
|
@ -159,10 +162,10 @@ public class MultiPhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slop == 0)
|
if (slop == 0)
|
||||||
return new ExactPhraseScorer(this, tps, getPositions(), getSimilarity(searcher),
|
return new ExactPhraseScorer(this, tps, getPositions(), similarity,
|
||||||
reader.norms(field));
|
reader.norms(field));
|
||||||
else
|
else
|
||||||
return new SloppyPhraseScorer(this, tps, getPositions(), getSimilarity(searcher),
|
return new SloppyPhraseScorer(this, tps, getPositions(), similarity,
|
||||||
slop, reader.norms(field));
|
slop, reader.norms(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +242,7 @@ public class MultiPhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
return new MultiPhraseWeight(searcher);
|
return new MultiPhraseWeight(searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,10 @@ package org.apache.lucene.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
@ -27,6 +31,93 @@ import org.apache.lucene.index.Term;
|
||||||
* or {@link #search(Query,Filter)} methods.
|
* or {@link #search(Query,Filter)} methods.
|
||||||
*/
|
*/
|
||||||
public class MultiSearcher extends Searcher {
|
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.
|
||||||
|
*/
|
||||||
|
private static class CachedDfSource extends Searcher {
|
||||||
|
private Map dfMap; // Map from Terms to corresponding doc freqs
|
||||||
|
private int maxDoc; // document count
|
||||||
|
|
||||||
|
public CachedDfSource(Map dfMap, int maxDoc) {
|
||||||
|
this.dfMap = dfMap;
|
||||||
|
this.maxDoc = maxDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int docFreq(Term term) {
|
||||||
|
int df;
|
||||||
|
try {
|
||||||
|
df = ((Integer) dfMap.get(term)).intValue();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new IllegalArgumentException("df for term " + term.text()
|
||||||
|
+ " not available");
|
||||||
|
}
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int maxDoc() {
|
||||||
|
return maxDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query rewrite(Query query) throws IOException {
|
||||||
|
// this is a bit of a hack. We know that a query which
|
||||||
|
// creates a Weight based on this Dummy-Searcher is
|
||||||
|
// always already rewritten (see preparedWeight()).
|
||||||
|
// Therefore we just return the unmodified query here
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Document doc(int i) throws IOException{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Explanation explain(Query query,int doc) throws IOException{
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Explanation explain(Weight weight,int doc) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void search(Query query, Filter filter, HitCollector results) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void search(Weight weight, Filter filter, HitCollector results) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopDocs search(Query query,Filter filter,int n) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopDocs search(Weight weight,Filter filter,int n) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopFieldDocs search(Query query,Filter filter,int n,Sort sort) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopFieldDocs search(Weight weight,Filter filter,int n,Sort sort) throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
private Searchable[] searchables;
|
private Searchable[] searchables;
|
||||||
private int[] starts;
|
private int[] starts;
|
||||||
private int maxDoc = 0;
|
private int maxDoc = 0;
|
||||||
|
@ -114,11 +205,18 @@ public class MultiSearcher extends Searcher {
|
||||||
|
|
||||||
public TopDocs search(Query query, Filter filter, int nDocs)
|
public TopDocs search(Query query, Filter filter, int nDocs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
Weight weight = prepareWeight(query);
|
||||||
|
return search(weight, filter, nDocs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopDocs search(Weight weight, Filter filter, int nDocs)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
HitQueue hq = new HitQueue(nDocs);
|
HitQueue hq = new HitQueue(nDocs);
|
||||||
int totalHits = 0;
|
int totalHits = 0;
|
||||||
|
|
||||||
for (int i = 0; i < searchables.length; i++) { // search each searcher
|
for (int i = 0; i < searchables.length; i++) { // search each searcher
|
||||||
TopDocs docs = searchables[i].search(query, filter, nDocs);
|
TopDocs docs = searchables[i].search(weight, filter, nDocs);
|
||||||
totalHits += docs.totalHits; // update totalHits
|
totalHits += docs.totalHits; // update totalHits
|
||||||
ScoreDoc[] scoreDocs = docs.scoreDocs;
|
ScoreDoc[] scoreDocs = docs.scoreDocs;
|
||||||
for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
|
for (int j = 0; j < scoreDocs.length; j++) { // merge scoreDocs into hq
|
||||||
|
@ -139,11 +237,17 @@ public class MultiSearcher extends Searcher {
|
||||||
|
|
||||||
public TopFieldDocs search (Query query, Filter filter, int n, Sort sort)
|
public TopFieldDocs search (Query query, Filter filter, int n, Sort sort)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
Weight weight = prepareWeight(query);
|
||||||
|
return search(weight, filter, n, sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort)
|
||||||
|
throws IOException {
|
||||||
FieldDocSortedHitQueue hq = null;
|
FieldDocSortedHitQueue hq = null;
|
||||||
int totalHits = 0;
|
int totalHits = 0;
|
||||||
|
|
||||||
for (int i = 0; i < searchables.length; i++) { // search each searcher
|
for (int i = 0; i < searchables.length; i++) { // search each searcher
|
||||||
TopFieldDocs docs = searchables[i].search (query, filter, n, sort);
|
TopFieldDocs docs = searchables[i].search (weight, filter, n, sort);
|
||||||
if (hq == null) hq = new FieldDocSortedHitQueue (docs.fields, n);
|
if (hq == null) hq = new FieldDocSortedHitQueue (docs.fields, n);
|
||||||
totalHits += docs.totalHits; // update totalHits
|
totalHits += docs.totalHits; // update totalHits
|
||||||
ScoreDoc[] scoreDocs = docs.scoreDocs;
|
ScoreDoc[] scoreDocs = docs.scoreDocs;
|
||||||
|
@ -165,12 +269,19 @@ public class MultiSearcher extends Searcher {
|
||||||
|
|
||||||
// inherit javadoc
|
// inherit javadoc
|
||||||
public void search(Query query, Filter filter, final HitCollector results)
|
public void search(Query query, Filter filter, final HitCollector results)
|
||||||
|
throws IOException {
|
||||||
|
Weight weight = prepareWeight(query);
|
||||||
|
search(weight, filter, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
// inherit javadoc
|
||||||
|
public void search(Weight weight, Filter filter, final HitCollector results)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
for (int i = 0; i < searchables.length; i++) {
|
for (int i = 0; i < searchables.length; i++) {
|
||||||
|
|
||||||
final int start = starts[i];
|
final int start = starts[i];
|
||||||
|
|
||||||
searchables[i].search(query, filter, new HitCollector() {
|
searchables[i].search(weight, filter, new HitCollector() {
|
||||||
public void collect(int doc, float score) {
|
public void collect(int doc, float score) {
|
||||||
results.collect(doc + start, score);
|
results.collect(doc + start, score);
|
||||||
}
|
}
|
||||||
|
@ -184,12 +295,62 @@ public class MultiSearcher extends Searcher {
|
||||||
for (int i = 0; i < searchables.length; i++) {
|
for (int i = 0; i < searchables.length; i++) {
|
||||||
queries[i] = searchables[i].rewrite(original);
|
queries[i] = searchables[i].rewrite(original);
|
||||||
}
|
}
|
||||||
return original.combine(queries);
|
return queries[0].combine(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Explanation explain(Query query, int doc) throws IOException {
|
public Explanation explain(Query query, int doc) throws IOException {
|
||||||
|
Weight weight = prepareWeight(query);
|
||||||
|
return explain(weight, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Explanation explain(Weight weight, int doc) throws IOException {
|
||||||
int i = subSearcher(doc); // find searcher index
|
int i = subSearcher(doc); // find searcher index
|
||||||
return searchables[i].explain(query,doc-starts[i]); // dispatch to searcher
|
return searchables[i].explain(weight,doc-starts[i]); // dispatch to searcher
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distributed query processing is done in the following steps:
|
||||||
|
* 1. rewrite query
|
||||||
|
* 2. extract necessary terms
|
||||||
|
* 3. collect dfs for these terms from the Searchables
|
||||||
|
* 4. create query weight using aggregate dfs.
|
||||||
|
* 5. distribute that weight to Searchables
|
||||||
|
* 6. merge results
|
||||||
|
*
|
||||||
|
* Steps 1-4 are done here, 5+6 in the search() methods
|
||||||
|
*
|
||||||
|
* @return rewritten queries
|
||||||
|
*/
|
||||||
|
private Weight prepareWeight(Query original) throws IOException {
|
||||||
|
// step 1
|
||||||
|
Query rewrittenQuery = rewrite(original);
|
||||||
|
|
||||||
|
// step 2
|
||||||
|
Set terms = new HashSet();
|
||||||
|
rewrittenQuery.extractTerms(terms);
|
||||||
|
|
||||||
|
// step3
|
||||||
|
Term[] allTermsArray = new Term[terms.size()];
|
||||||
|
terms.toArray(allTermsArray);
|
||||||
|
int[] aggregatedDfs = new int[terms.size()];
|
||||||
|
for (int i = 0; i < searchables.length; i++) {
|
||||||
|
int[] dfs = searchables[i].docFreqs(allTermsArray);
|
||||||
|
for(int j=0; j<aggregatedDfs.length; j++){
|
||||||
|
aggregatedDfs[j] += dfs[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap dfMap = new HashMap();
|
||||||
|
for(int i=0; i<allTermsArray.length; i++) {
|
||||||
|
dfMap.put(allTermsArray[i], new Integer(aggregatedDfs[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// step4
|
||||||
|
int numDocs = maxDoc();
|
||||||
|
CachedDfSource cacheSim = new CachedDfSource(dfMap, numDocs);
|
||||||
|
|
||||||
|
return rewrittenQuery.weight(cacheSim);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
* TODO: parallelize this one too
|
* TODO: parallelize this one too
|
||||||
*/
|
*/
|
||||||
public int docFreq(Term term) throws IOException {
|
public int docFreq(Term term) throws IOException {
|
||||||
int docFreq = 0;
|
return super.docFreq(term);
|
||||||
for (int i = 0; i < searchables.length; i++)
|
|
||||||
docFreq += searchables[i].docFreq(term);
|
|
||||||
return docFreq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +50,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
* Searchable, waits for each search to complete and merge
|
* Searchable, waits for each search to complete and merge
|
||||||
* the results back together.
|
* the results back together.
|
||||||
*/
|
*/
|
||||||
public TopDocs search(Query query, Filter filter, int nDocs)
|
public TopDocs search(Weight weight, Filter filter, int nDocs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
HitQueue hq = new HitQueue(nDocs);
|
HitQueue hq = new HitQueue(nDocs);
|
||||||
int totalHits = 0;
|
int totalHits = 0;
|
||||||
|
@ -64,7 +61,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
msta[i] =
|
msta[i] =
|
||||||
new MultiSearcherThread(
|
new MultiSearcherThread(
|
||||||
searchables[i],
|
searchables[i],
|
||||||
query,
|
weight,
|
||||||
filter,
|
filter,
|
||||||
nDocs,
|
nDocs,
|
||||||
hq,
|
hq,
|
||||||
|
@ -101,7 +98,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
* Searchable, waits for each search to complete and merges
|
* Searchable, waits for each search to complete and merges
|
||||||
* the results back together.
|
* the results back together.
|
||||||
*/
|
*/
|
||||||
public TopFieldDocs search(Query query, Filter filter, int nDocs, Sort sort)
|
public TopFieldDocs search(Weight weight, Filter filter, int nDocs, Sort sort)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// don't specify the fields - we'll wait to do this until we get results
|
// don't specify the fields - we'll wait to do this until we get results
|
||||||
FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue (null, nDocs);
|
FieldDocSortedHitQueue hq = new FieldDocSortedHitQueue (null, nDocs);
|
||||||
|
@ -112,7 +109,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
msta[i] =
|
msta[i] =
|
||||||
new MultiSearcherThread(
|
new MultiSearcherThread(
|
||||||
searchables[i],
|
searchables[i],
|
||||||
query,
|
weight,
|
||||||
filter,
|
filter,
|
||||||
nDocs,
|
nDocs,
|
||||||
hq,
|
hq,
|
||||||
|
@ -181,11 +178,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
* @see org.apache.lucene.search.Searchable#rewrite(org.apache.lucene.search.Query)
|
* @see org.apache.lucene.search.Searchable#rewrite(org.apache.lucene.search.Query)
|
||||||
*/
|
*/
|
||||||
public Query rewrite(Query original) throws IOException {
|
public Query rewrite(Query original) throws IOException {
|
||||||
Query[] queries = new Query[searchables.length];
|
return super.rewrite(original);
|
||||||
for (int i = 0; i < searchables.length; i++) {
|
|
||||||
queries[i] = searchables[i].rewrite(original);
|
|
||||||
}
|
|
||||||
return original.combine(queries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -196,7 +189,7 @@ public class ParallelMultiSearcher extends MultiSearcher {
|
||||||
class MultiSearcherThread extends Thread {
|
class MultiSearcherThread extends Thread {
|
||||||
|
|
||||||
private Searchable searchable;
|
private Searchable searchable;
|
||||||
private Query query;
|
private Weight weight;
|
||||||
private Filter filter;
|
private Filter filter;
|
||||||
private int nDocs;
|
private int nDocs;
|
||||||
private TopDocs docs;
|
private TopDocs docs;
|
||||||
|
@ -208,7 +201,7 @@ class MultiSearcherThread extends Thread {
|
||||||
|
|
||||||
public MultiSearcherThread(
|
public MultiSearcherThread(
|
||||||
Searchable searchable,
|
Searchable searchable,
|
||||||
Query query,
|
Weight weight,
|
||||||
Filter filter,
|
Filter filter,
|
||||||
int nDocs,
|
int nDocs,
|
||||||
HitQueue hq,
|
HitQueue hq,
|
||||||
|
@ -217,7 +210,7 @@ class MultiSearcherThread extends Thread {
|
||||||
String name) {
|
String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.searchable = searchable;
|
this.searchable = searchable;
|
||||||
this.query = query;
|
this.weight = weight;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.nDocs = nDocs;
|
this.nDocs = nDocs;
|
||||||
this.hq = hq;
|
this.hq = hq;
|
||||||
|
@ -227,7 +220,7 @@ class MultiSearcherThread extends Thread {
|
||||||
|
|
||||||
public MultiSearcherThread(
|
public MultiSearcherThread(
|
||||||
Searchable searchable,
|
Searchable searchable,
|
||||||
Query query,
|
Weight weight,
|
||||||
Filter filter,
|
Filter filter,
|
||||||
int nDocs,
|
int nDocs,
|
||||||
FieldDocSortedHitQueue hq,
|
FieldDocSortedHitQueue hq,
|
||||||
|
@ -237,7 +230,7 @@ class MultiSearcherThread extends Thread {
|
||||||
String name) {
|
String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.searchable = searchable;
|
this.searchable = searchable;
|
||||||
this.query = query;
|
this.weight = weight;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.nDocs = nDocs;
|
this.nDocs = nDocs;
|
||||||
this.hq = hq;
|
this.hq = hq;
|
||||||
|
@ -248,8 +241,8 @@ class MultiSearcherThread extends Thread {
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
docs = (sort == null) ? searchable.search (query, filter, nDocs)
|
docs = (sort == null) ? searchable.search (weight, filter, nDocs)
|
||||||
: searchable.search (query, filter, nDocs, sort);
|
: searchable.search (weight, filter, nDocs, sort);
|
||||||
}
|
}
|
||||||
// Store the IOException for later use by the caller of this thread
|
// Store the IOException for later use by the caller of this thread
|
||||||
catch (IOException ioe) {
|
catch (IOException ioe) {
|
||||||
|
|
|
@ -108,27 +108,30 @@ public class PhrasePrefixQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PhrasePrefixWeight implements Weight {
|
private class PhrasePrefixWeight implements Weight {
|
||||||
private Searcher searcher;
|
private Similarity similarity;
|
||||||
private float value;
|
private float value;
|
||||||
private float idf;
|
private float idf;
|
||||||
private float queryNorm;
|
private float queryNorm;
|
||||||
private float queryWeight;
|
private float queryWeight;
|
||||||
|
|
||||||
public PhrasePrefixWeight(Searcher searcher) {
|
public PhrasePrefixWeight(Searcher searcher)
|
||||||
this.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<terms.length; j++) {
|
||||||
|
idf += getSimilarity(searcher).idf(terms[j], searcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query getQuery() { return PhrasePrefixQuery.this; }
|
public Query getQuery() { return PhrasePrefixQuery.this; }
|
||||||
public float getValue() { return value; }
|
public float getValue() { return value; }
|
||||||
|
|
||||||
public float sumOfSquaredWeights() throws IOException {
|
public float sumOfSquaredWeights() throws IOException {
|
||||||
Iterator i = termArrays.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
Term[] terms = (Term[])i.next();
|
|
||||||
for (int j=0; j<terms.length; j++)
|
|
||||||
idf += getSimilarity(searcher).idf(terms[j], searcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
queryWeight = idf * getBoost(); // compute query weight
|
queryWeight = idf * getBoost(); // compute query weight
|
||||||
return queryWeight * queryWeight; // square it
|
return queryWeight * queryWeight; // square it
|
||||||
}
|
}
|
||||||
|
@ -160,10 +163,10 @@ public class PhrasePrefixQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slop == 0)
|
if (slop == 0)
|
||||||
return new ExactPhraseScorer(this, tps, getPositions(), getSimilarity(searcher),
|
return new ExactPhraseScorer(this, tps, getPositions(), similarity,
|
||||||
reader.norms(field));
|
reader.norms(field));
|
||||||
else
|
else
|
||||||
return new SloppyPhraseScorer(this, tps, getPositions(), getSimilarity(searcher),
|
return new SloppyPhraseScorer(this, tps, getPositions(), similarity,
|
||||||
slop, reader.norms(field));
|
slop, reader.norms(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +229,7 @@ public class PhrasePrefixQuery extends Query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
if (termArrays.size() == 1) { // optimize one-term case
|
if (termArrays.size() == 1) { // optimize one-term case
|
||||||
Term[] terms = (Term[])termArrays.get(0);
|
Term[] terms = (Term[])termArrays.get(0);
|
||||||
BooleanQuery boq = new BooleanQuery(true);
|
BooleanQuery boq = new BooleanQuery(true);
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.lucene.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
@ -100,14 +101,17 @@ public class PhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PhraseWeight implements Weight {
|
private class PhraseWeight implements Weight {
|
||||||
private Searcher searcher;
|
private Similarity similarity;
|
||||||
private float value;
|
private float value;
|
||||||
private float idf;
|
private float idf;
|
||||||
private float queryNorm;
|
private float queryNorm;
|
||||||
private float queryWeight;
|
private float queryWeight;
|
||||||
|
|
||||||
public PhraseWeight(Searcher searcher) {
|
public PhraseWeight(Searcher searcher)
|
||||||
this.searcher = searcher;
|
throws IOException {
|
||||||
|
this.similarity = getSimilarity(searcher);
|
||||||
|
|
||||||
|
idf = similarity.idf(terms, searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() { return "weight(" + PhraseQuery.this + ")"; }
|
public String toString() { return "weight(" + PhraseQuery.this + ")"; }
|
||||||
|
@ -116,7 +120,6 @@ public class PhraseQuery extends Query {
|
||||||
public float getValue() { return value; }
|
public float getValue() { return value; }
|
||||||
|
|
||||||
public float sumOfSquaredWeights() throws IOException {
|
public float sumOfSquaredWeights() throws IOException {
|
||||||
idf = getSimilarity(searcher).idf(terms, searcher);
|
|
||||||
queryWeight = idf * getBoost(); // compute query weight
|
queryWeight = idf * getBoost(); // compute query weight
|
||||||
return queryWeight * queryWeight; // square it
|
return queryWeight * queryWeight; // square it
|
||||||
}
|
}
|
||||||
|
@ -140,11 +143,11 @@ public class PhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slop == 0) // optimize exact case
|
if (slop == 0) // optimize exact case
|
||||||
return new ExactPhraseScorer(this, tps, getPositions(), getSimilarity(searcher),
|
return new ExactPhraseScorer(this, tps, getPositions(), similarity,
|
||||||
reader.norms(field));
|
reader.norms(field));
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
new SloppyPhraseScorer(this, tps, getPositions(), getSimilarity(searcher), slop,
|
new SloppyPhraseScorer(this, tps, getPositions(), similarity, slop,
|
||||||
reader.norms(field));
|
reader.norms(field));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -168,7 +171,7 @@ public class PhraseQuery extends Query {
|
||||||
|
|
||||||
docFreqs.append(term.text());
|
docFreqs.append(term.text());
|
||||||
docFreqs.append("=");
|
docFreqs.append("=");
|
||||||
docFreqs.append(searcher.docFreq(term));
|
docFreqs.append(reader.docFreq(term));
|
||||||
|
|
||||||
query.append(term.text());
|
query.append(term.text());
|
||||||
}
|
}
|
||||||
|
@ -228,7 +231,7 @@ public class PhraseQuery extends Query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
if (terms.size() == 1) { // optimize one-term case
|
if (terms.size() == 1) { // optimize one-term case
|
||||||
Term term = (Term)terms.elementAt(0);
|
Term term = (Term)terms.elementAt(0);
|
||||||
Query termQuery = new TermQuery(term);
|
Query termQuery = new TermQuery(term);
|
||||||
|
@ -238,6 +241,12 @@ public class PhraseQuery extends Query {
|
||||||
return new PhraseWeight(searcher);
|
return new PhraseWeight(searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.apache.lucene.search.Query#extractTerms(java.util.Set)
|
||||||
|
*/
|
||||||
|
public void extractTerms(Set queryTerms) {
|
||||||
|
queryTerms.addAll(terms);
|
||||||
|
}
|
||||||
|
|
||||||
/** Prints a user-readable version of this query. */
|
/** Prints a user-readable version of this query. */
|
||||||
public String toString(String f) {
|
public String toString(String f) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ public abstract class Query implements java.io.Serializable, Cloneable {
|
||||||
*
|
*
|
||||||
* <p>Only implemented by primitive queries, which re-write to themselves.
|
* <p>Only implemented by primitive queries, which re-write to themselves.
|
||||||
*/
|
*/
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +108,19 @@ public abstract class Query implements java.io.Serializable, Cloneable {
|
||||||
* {@link #createWeight(Searcher)} implementatation.
|
* {@link #createWeight(Searcher)} implementatation.
|
||||||
*/
|
*/
|
||||||
public Query combine(Query[] queries) {
|
public Query combine(Query[] queries) {
|
||||||
|
for (int i = 0; i < queries.length; i++) {
|
||||||
|
if (!this.equals(queries[i])) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expert: adds all terms occuring in this query to the terms set
|
||||||
|
*/
|
||||||
|
public void extractTerms(Set terms) {
|
||||||
|
// needs to be implemented by query subclasses
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ public class RemoteSearchable
|
||||||
local.search(query, filter, results);
|
local.search(query, filter, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void search(Weight weight, Filter filter, HitCollector results)
|
||||||
|
throws IOException {
|
||||||
|
local.search(weight, filter, results);
|
||||||
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
local.close();
|
local.close();
|
||||||
}
|
}
|
||||||
|
@ -52,6 +57,11 @@ public class RemoteSearchable
|
||||||
return local.docFreq(term);
|
return local.docFreq(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int[] docFreqs(Term[] terms) throws IOException {
|
||||||
|
return local.docFreqs(terms);
|
||||||
|
}
|
||||||
|
|
||||||
public int maxDoc() throws IOException {
|
public int maxDoc() throws IOException {
|
||||||
return local.maxDoc();
|
return local.maxDoc();
|
||||||
}
|
}
|
||||||
|
@ -60,11 +70,20 @@ public class RemoteSearchable
|
||||||
return local.search(query, filter, n);
|
return local.search(query, filter, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TopDocs search(Weight weight, Filter filter, int n) throws IOException {
|
||||||
|
return local.search(weight, filter, n);
|
||||||
|
}
|
||||||
|
|
||||||
public TopFieldDocs search (Query query, Filter filter, int n, Sort sort)
|
public TopFieldDocs search (Query query, Filter filter, int n, Sort sort)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return local.search (query, filter, n, sort);
|
return local.search (query, filter, n, sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TopFieldDocs search (Weight weight, Filter filter, int n, Sort sort)
|
||||||
|
throws IOException {
|
||||||
|
return local.search (weight, filter, n, sort);
|
||||||
|
}
|
||||||
|
|
||||||
public Document doc(int i) throws IOException {
|
public Document doc(int i) throws IOException {
|
||||||
return local.doc(i);
|
return local.doc(i);
|
||||||
}
|
}
|
||||||
|
@ -77,6 +96,10 @@ public class RemoteSearchable
|
||||||
return local.explain(query, doc);
|
return local.explain(query, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Explanation explain(Weight weight, int doc) throws IOException {
|
||||||
|
return local.explain(weight, doc);
|
||||||
|
}
|
||||||
|
|
||||||
/** Exports a searcher for the index in args[0] named
|
/** Exports a searcher for the index in args[0] named
|
||||||
* "//localhost/Searchable". */
|
* "//localhost/Searchable". */
|
||||||
public static void main(String args[]) throws Exception {
|
public static void main(String args[]) throws Exception {
|
||||||
|
|
|
@ -48,10 +48,19 @@ public interface Searchable extends java.rmi.Remote {
|
||||||
* @param filter if non-null, a bitset used to eliminate some documents
|
* @param filter if non-null, a bitset used to eliminate some documents
|
||||||
* @param results to receive hits
|
* @param results to receive hits
|
||||||
* @throws BooleanQuery.TooManyClauses
|
* @throws BooleanQuery.TooManyClauses
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
void search(Query query, Filter filter, HitCollector results)
|
void search(Query query, Filter filter, HitCollector results)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
|
/** Expert: Low-level search implementation.
|
||||||
|
* Identical to {@link #search(Query, Filter, HitCollector)}, but takes
|
||||||
|
* a Weight instead of a query.
|
||||||
|
*/
|
||||||
|
void search(Weight weight, Filter filter, HitCollector results)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
/** Frees resources associated with this Searcher.
|
/** Frees resources associated with this Searcher.
|
||||||
* Be careful not to call this method while you are still using objects
|
* Be careful not to call this method while you are still using objects
|
||||||
* like {@link Hits}.
|
* like {@link Hits}.
|
||||||
|
@ -64,6 +73,12 @@ public interface Searchable extends java.rmi.Remote {
|
||||||
*/
|
*/
|
||||||
int docFreq(Term term) throws IOException;
|
int docFreq(Term term) throws IOException;
|
||||||
|
|
||||||
|
/** Expert: For each term in the terms array, calculates the number of
|
||||||
|
* documents containing <code>term</code>. 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.
|
/** Expert: Returns one greater than the largest possible document number.
|
||||||
* Called by search code to compute term weights.
|
* Called by search code to compute term weights.
|
||||||
* @see IndexReader#maxDoc()
|
* @see IndexReader#maxDoc()
|
||||||
|
@ -78,9 +93,17 @@ public interface Searchable extends java.rmi.Remote {
|
||||||
* <p>Applications should usually call {@link Searcher#search(Query)} or
|
* <p>Applications should usually call {@link Searcher#search(Query)} or
|
||||||
* {@link Searcher#search(Query,Filter)} instead.
|
* {@link Searcher#search(Query,Filter)} instead.
|
||||||
* @throws BooleanQuery.TooManyClauses
|
* @throws BooleanQuery.TooManyClauses
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
TopDocs search(Query query, Filter filter, int n) throws IOException;
|
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 <code>i</code>.
|
/** Expert: Returns the stored fields of document <code>i</code>.
|
||||||
* Called by {@link HitCollector} implementations.
|
* Called by {@link HitCollector} implementations.
|
||||||
* @see IndexReader#document(int)
|
* @see IndexReader#document(int)
|
||||||
|
@ -103,6 +126,12 @@ public interface Searchable extends java.rmi.Remote {
|
||||||
*/
|
*/
|
||||||
Explanation explain(Query query, int doc) throws IOException;
|
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
|
/** Expert: Low-level search implementation with arbitrary sorting. Finds
|
||||||
* the top <code>n</code> hits for <code>query</code>, applying
|
* the top <code>n</code> hits for <code>query</code>, applying
|
||||||
* <code>filter</code> if non-null, and sorting the hits by the criteria in
|
* <code>filter</code> if non-null, and sorting the hits by the criteria in
|
||||||
|
@ -111,7 +140,16 @@ public interface Searchable extends java.rmi.Remote {
|
||||||
* <p>Applications should usually call {@link
|
* <p>Applications should usually call {@link
|
||||||
* Searcher#search(Query,Filter,Sort)} instead.
|
* Searcher#search(Query,Filter,Sort)} instead.
|
||||||
* @throws BooleanQuery.TooManyClauses
|
* @throws BooleanQuery.TooManyClauses
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
TopFieldDocs search(Query query, Filter filter, int n, Sort sort)
|
TopFieldDocs search(Query query, Filter filter, int n, Sort sort)
|
||||||
throws IOException;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ package org.apache.lucene.search;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.lucene.index.Term;
|
||||||
|
|
||||||
/** An abstract base class for search implementations.
|
/** An abstract base class for search implementations.
|
||||||
* Implements some common utility methods.
|
* Implements some common utility methods.
|
||||||
*/
|
*/
|
||||||
|
@ -93,4 +95,15 @@ public abstract class Searcher implements Searchable {
|
||||||
public Similarity getSimilarity() {
|
public Similarity getSimilarity() {
|
||||||
return this.similarity;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.lucene.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -84,7 +85,7 @@ import org.apache.lucene.document.Field; // for javadoc
|
||||||
* @see IndexWriter#setSimilarity(Similarity)
|
* @see IndexWriter#setSimilarity(Similarity)
|
||||||
* @see Searcher#setSimilarity(Similarity)
|
* @see Searcher#setSimilarity(Similarity)
|
||||||
*/
|
*/
|
||||||
public abstract class Similarity {
|
public abstract class Similarity implements Serializable {
|
||||||
/** The Similarity implementation used by default. */
|
/** The Similarity implementation used by default. */
|
||||||
private static Similarity defaultImpl = new DefaultSimilarity();
|
private static Similarity defaultImpl = new DefaultSimilarity();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ package org.apache.lucene.search;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermDocs;
|
import org.apache.lucene.index.TermDocs;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
@ -28,14 +30,17 @@ public class TermQuery extends Query {
|
||||||
private Term term;
|
private Term term;
|
||||||
|
|
||||||
private class TermWeight implements Weight {
|
private class TermWeight implements Weight {
|
||||||
|
private Similarity similarity;
|
||||||
private Searcher searcher;
|
private Searcher searcher;
|
||||||
private float value;
|
private float value;
|
||||||
private float idf;
|
private float idf;
|
||||||
private float queryNorm;
|
private float queryNorm;
|
||||||
private float queryWeight;
|
private float queryWeight;
|
||||||
|
|
||||||
public TermWeight(Searcher searcher) {
|
public TermWeight(Searcher searcher)
|
||||||
this.searcher = searcher;
|
throws IOException {
|
||||||
|
this.similarity = getSimilarity(searcher);
|
||||||
|
idf = similarity.idf(term, searcher); // compute idf
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() { return "weight(" + TermQuery.this + ")"; }
|
public String toString() { return "weight(" + TermQuery.this + ")"; }
|
||||||
|
@ -44,7 +49,6 @@ public class TermQuery extends Query {
|
||||||
public float getValue() { return value; }
|
public float getValue() { return value; }
|
||||||
|
|
||||||
public float sumOfSquaredWeights() throws IOException {
|
public float sumOfSquaredWeights() throws IOException {
|
||||||
idf = getSimilarity(searcher).idf(term, searcher); // compute idf
|
|
||||||
queryWeight = idf * getBoost(); // compute query weight
|
queryWeight = idf * getBoost(); // compute query weight
|
||||||
return queryWeight * queryWeight; // square it
|
return queryWeight * queryWeight; // square it
|
||||||
}
|
}
|
||||||
|
@ -52,16 +56,16 @@ public class TermQuery extends Query {
|
||||||
public void normalize(float queryNorm) {
|
public void normalize(float queryNorm) {
|
||||||
this.queryNorm = queryNorm;
|
this.queryNorm = queryNorm;
|
||||||
queryWeight *= queryNorm; // normalize query weight
|
queryWeight *= queryNorm; // normalize query weight
|
||||||
value = queryWeight * idf; // idf for document
|
value = queryWeight * idf; // idf for document
|
||||||
}
|
}
|
||||||
|
|
||||||
public Scorer scorer(IndexReader reader) throws IOException {
|
public Scorer scorer(IndexReader reader) throws IOException {
|
||||||
TermDocs termDocs = reader.termDocs(term);
|
TermDocs termDocs = reader.termDocs(term);
|
||||||
|
|
||||||
if (termDocs == null)
|
if (termDocs == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new TermScorer(this, termDocs, getSimilarity(searcher),
|
return new TermScorer(this, termDocs, similarity,
|
||||||
reader.norms(term.field()));
|
reader.norms(term.field()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +76,7 @@ public class TermQuery extends Query {
|
||||||
result.setDescription("weight("+getQuery()+" in "+doc+"), product of:");
|
result.setDescription("weight("+getQuery()+" in "+doc+"), product of:");
|
||||||
|
|
||||||
Explanation idfExpl =
|
Explanation idfExpl =
|
||||||
new Explanation(idf, "idf(docFreq=" + searcher.docFreq(term) + ")");
|
new Explanation(idf, "idf(docFreq=" + reader.docFreq(term) + ")");
|
||||||
|
|
||||||
// explain query weight
|
// explain query weight
|
||||||
Explanation queryExpl = new Explanation();
|
Explanation queryExpl = new Explanation();
|
||||||
|
@ -82,16 +86,16 @@ public class TermQuery extends Query {
|
||||||
if (getBoost() != 1.0f)
|
if (getBoost() != 1.0f)
|
||||||
queryExpl.addDetail(boostExpl);
|
queryExpl.addDetail(boostExpl);
|
||||||
queryExpl.addDetail(idfExpl);
|
queryExpl.addDetail(idfExpl);
|
||||||
|
|
||||||
Explanation queryNormExpl = new Explanation(queryNorm,"queryNorm");
|
Explanation queryNormExpl = new Explanation(queryNorm,"queryNorm");
|
||||||
queryExpl.addDetail(queryNormExpl);
|
queryExpl.addDetail(queryNormExpl);
|
||||||
|
|
||||||
queryExpl.setValue(boostExpl.getValue() *
|
queryExpl.setValue(boostExpl.getValue() *
|
||||||
idfExpl.getValue() *
|
idfExpl.getValue() *
|
||||||
queryNormExpl.getValue());
|
queryNormExpl.getValue());
|
||||||
|
|
||||||
result.addDetail(queryExpl);
|
result.addDetail(queryExpl);
|
||||||
|
|
||||||
// explain field weight
|
// explain field weight
|
||||||
String field = term.field();
|
String field = term.field();
|
||||||
Explanation fieldExpl = new Explanation();
|
Explanation fieldExpl = new Explanation();
|
||||||
|
@ -113,7 +117,7 @@ public class TermQuery extends Query {
|
||||||
fieldExpl.setValue(tfExpl.getValue() *
|
fieldExpl.setValue(tfExpl.getValue() *
|
||||||
idfExpl.getValue() *
|
idfExpl.getValue() *
|
||||||
fieldNormExpl.getValue());
|
fieldNormExpl.getValue());
|
||||||
|
|
||||||
result.addDetail(fieldExpl);
|
result.addDetail(fieldExpl);
|
||||||
|
|
||||||
// combine them
|
// combine them
|
||||||
|
@ -134,10 +138,14 @@ public class TermQuery extends Query {
|
||||||
/** Returns the term of this query. */
|
/** Returns the term of this query. */
|
||||||
public Term getTerm() { return term; }
|
public Term getTerm() { return term; }
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
return new TermWeight(searcher);
|
return new TermWeight(searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void extractTerms(Set terms) {
|
||||||
|
terms.add(getTerm());
|
||||||
|
}
|
||||||
|
|
||||||
/** Prints a user-readable version of this query. */
|
/** Prints a user-readable version of this query. */
|
||||||
public String toString(String field) {
|
public String toString(String field) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
|
@ -37,7 +37,7 @@ public abstract class SpanQuery extends Query {
|
||||||
/** Returns a collection of all terms matched by this query.*/
|
/** Returns a collection of all terms matched by this query.*/
|
||||||
public abstract Collection getTerms();
|
public abstract Collection getTerms();
|
||||||
|
|
||||||
protected Weight createWeight(Searcher searcher) {
|
protected Weight createWeight(Searcher searcher) throws IOException {
|
||||||
return new SpanWeight(this, searcher);
|
return new SpanWeight(this, searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.apache.lucene.search.Explanation;
|
||||||
import org.apache.lucene.search.Similarity;
|
import org.apache.lucene.search.Similarity;
|
||||||
|
|
||||||
class SpanWeight implements Weight {
|
class SpanWeight implements Weight {
|
||||||
private Searcher searcher;
|
private Similarity similarity;
|
||||||
private float value;
|
private float value;
|
||||||
private float idf;
|
private float idf;
|
||||||
private float queryNorm;
|
private float queryNorm;
|
||||||
|
@ -41,17 +41,19 @@ class SpanWeight implements Weight {
|
||||||
private Collection terms;
|
private Collection terms;
|
||||||
private SpanQuery query;
|
private SpanQuery query;
|
||||||
|
|
||||||
public SpanWeight(SpanQuery query, Searcher searcher) {
|
public SpanWeight(SpanQuery query, Searcher searcher)
|
||||||
this.searcher = searcher;
|
throws IOException {
|
||||||
|
this.similarity = query.getSimilarity(searcher);
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.terms = query.getTerms();
|
this.terms = query.getTerms();
|
||||||
|
|
||||||
|
idf = this.query.getSimilarity(searcher).idf(terms, searcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query getQuery() { return query; }
|
public Query getQuery() { return query; }
|
||||||
public float getValue() { return value; }
|
public float getValue() { return value; }
|
||||||
|
|
||||||
public float sumOfSquaredWeights() throws IOException {
|
public float sumOfSquaredWeights() throws IOException {
|
||||||
idf = this.query.getSimilarity(searcher).idf(terms, searcher);
|
|
||||||
queryWeight = idf * query.getBoost(); // compute query weight
|
queryWeight = idf * query.getBoost(); // compute query weight
|
||||||
return queryWeight * queryWeight; // square it
|
return queryWeight * queryWeight; // square it
|
||||||
}
|
}
|
||||||
|
@ -64,7 +66,7 @@ class SpanWeight implements Weight {
|
||||||
|
|
||||||
public Scorer scorer(IndexReader reader) throws IOException {
|
public Scorer scorer(IndexReader reader) throws IOException {
|
||||||
return new SpanScorer(query.getSpans(reader), this,
|
return new SpanScorer(query.getSpans(reader), this,
|
||||||
query.getSimilarity(searcher),
|
similarity,
|
||||||
reader.norms(query.getField()));
|
reader.norms(query.getField()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ class SpanWeight implements Weight {
|
||||||
Term term = (Term)i.next();
|
Term term = (Term)i.next();
|
||||||
docFreqs.append(term.text());
|
docFreqs.append(term.text());
|
||||||
docFreqs.append("=");
|
docFreqs.append("=");
|
||||||
docFreqs.append(searcher.docFreq(term));
|
docFreqs.append(reader.docFreq(term));
|
||||||
|
|
||||||
if (i.hasNext()) {
|
if (i.hasNext()) {
|
||||||
docFreqs.append(" ");
|
docFreqs.append(" ");
|
||||||
|
|
Loading…
Reference in New Issue