mirror of https://github.com/apache/lucene.git
LUCENE-1614: switch next -> nextDoc, skipTo -> advance, doc -> docID in DISI
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@782410 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9dbff2618f
commit
a93e2c41b0
13
CHANGES.txt
13
CHANGES.txt
|
@ -35,7 +35,7 @@ Changes in backwards compatibility policy
|
|||
code to implement this method. If you already extend
|
||||
IndexSearcher, no further changes are needed to use Collector.
|
||||
|
||||
Finally, the values Float.Nan, Float.NEGATIVE_INFINITY and
|
||||
Finally, the values Float.NaN, Float.NEGATIVE_INFINITY and
|
||||
Float.POSITIVE_INFINITY are not valid scores. Lucene uses these
|
||||
values internally in certain places, so if you have hits with such
|
||||
scores it will cause problems. (Shai Erera via Mike McCandless)
|
||||
|
@ -173,6 +173,17 @@ API Changes
|
|||
require up front specification of enablePositionIncrement (Mike
|
||||
McCandless)
|
||||
|
||||
18. LUCENE-1614: DocIdSetIterator's next() and skipTo() were deprecated in favor
|
||||
of the new nextDoc() and advance(). The new methods return the doc Id they
|
||||
landed on, saving an extra call to doc() in most cases.
|
||||
For easy migration of the code, you can change the calls to next() to
|
||||
nextDoc() != DocIdSetIterator.NO_MORE_DOCS and similarly for skipTo().
|
||||
However it is advised that you take advantage of the returned doc ID and not
|
||||
call doc() following those two.
|
||||
Also, doc() was deprecated in favor of docID(). docID() should return -1 or
|
||||
NO_MORE_DOCS if nextDoc/advance were not called yet, or NO_MORE_DOCS if the
|
||||
iterator has exhausted. Otherwise it should return the current doc ID.
|
||||
(Shai Erera via Mike McCandless)
|
||||
|
||||
Bug fixes
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<property name="Name" value="Lucene"/>
|
||||
<property name="dev.version" value="2.9-dev"/>
|
||||
<property name="version" value="${dev.version}"/>
|
||||
<property name="compatibility.tag" value="lucene_2_4_back_compat_tests_20090607a"/>
|
||||
<property name="compatibility.tag" value="lucene_2_4_back_compat_tests_20090607b"/>
|
||||
<property name="spec.version" value="${version}"/>
|
||||
<property name="year" value="2000-${current.year}"/>
|
||||
<property name="final.name" value="lucene-${name}-${version}"/>
|
||||
|
|
|
@ -20,16 +20,12 @@ package org.apache.lucene.misc;
|
|||
import junit.framework.TestCase;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.FSDirectory;
|
||||
import org.apache.lucene.store.NoLockFactory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
|
@ -77,7 +73,7 @@ public class ChainedFilterTest extends TestCase {
|
|||
query = bq;
|
||||
|
||||
// date filter matches everything too
|
||||
Date pastTheEnd = parseDate("2099 Jan 1");
|
||||
//Date pastTheEnd = parseDate("2099 Jan 1");
|
||||
// dateFilter = DateFilter.Before("date", pastTheEnd);
|
||||
// just treat dates as strings and select the whole range for now...
|
||||
dateFilter = new RangeFilter("date","","ZZZZ",true,true);
|
||||
|
@ -94,15 +90,17 @@ public class ChainedFilterTest extends TestCase {
|
|||
final Filter f = chain[i];
|
||||
// create old BitSet-based Filter as wrapper
|
||||
oldFilters[i] = new Filter() {
|
||||
/** @deprecated */
|
||||
public BitSet bits(IndexReader reader) throws IOException {
|
||||
BitSet bits = new BitSet(reader.maxDoc());
|
||||
DocIdSetIterator it = f.getDocIdSet(reader).iterator();
|
||||
while(it.next()) {
|
||||
bits.set(it.doc());
|
||||
DocIdSetIterator it = f.getDocIdSet(reader).iterator();
|
||||
int doc;
|
||||
while((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
bits.set(doc);
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
return oldFilters;
|
||||
}
|
||||
|
@ -211,37 +209,36 @@ public class ChainedFilterTest extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private Date parseDate(String s) throws ParseException {
|
||||
return new SimpleDateFormat("yyyy MMM dd", Locale.US).parse(s);
|
||||
}
|
||||
*/
|
||||
|
||||
public void testWithCachingFilter() throws Exception {
|
||||
for (int mode = 0; mode < 2; mode++) {
|
||||
boolean old = (mode==0);
|
||||
Directory dir = new RAMDirectory();
|
||||
Analyzer analyzer = new WhitespaceAnalyzer();
|
||||
Directory dir = new RAMDirectory();
|
||||
Analyzer analyzer = new WhitespaceAnalyzer();
|
||||
|
||||
IndexWriter writer = new IndexWriter(dir, analyzer, true, MaxFieldLength.LIMITED);
|
||||
writer.close();
|
||||
IndexWriter writer = new IndexWriter(dir, analyzer, true, MaxFieldLength.LIMITED);
|
||||
writer.close();
|
||||
|
||||
Searcher searcher = new IndexSearcher(dir);
|
||||
Searcher searcher = new IndexSearcher(dir);
|
||||
|
||||
Query query = new TermQuery(new Term("none", "none"));
|
||||
Query query = new TermQuery(new Term("none", "none"));
|
||||
|
||||
QueryWrapperFilter queryFilter = new QueryWrapperFilter(query);
|
||||
CachingWrapperFilter cachingFilter = new CachingWrapperFilter(queryFilter);
|
||||
QueryWrapperFilter queryFilter = new QueryWrapperFilter(query);
|
||||
CachingWrapperFilter cachingFilter = new CachingWrapperFilter(queryFilter);
|
||||
|
||||
searcher.search(query, cachingFilter, 1);
|
||||
searcher.search(query, cachingFilter, 1);
|
||||
|
||||
CachingWrapperFilter cachingFilter2 = new CachingWrapperFilter(queryFilter);
|
||||
Filter[] chain = new Filter[2];
|
||||
chain[0] = cachingFilter;
|
||||
chain[1] = cachingFilter2;
|
||||
ChainedFilter cf = new ChainedFilter(chain);
|
||||
CachingWrapperFilter cachingFilter2 = new CachingWrapperFilter(queryFilter);
|
||||
Filter[] chain = new Filter[2];
|
||||
chain[0] = cachingFilter;
|
||||
chain[1] = cachingFilter2;
|
||||
ChainedFilter cf = new ChainedFilter(chain);
|
||||
|
||||
// throws java.lang.ClassCastException: org.apache.lucene.util.OpenBitSet cannot be cast to java.util.BitSet
|
||||
searcher.search(new MatchAllDocsQuery(), cf, 1);
|
||||
}
|
||||
// throws java.lang.ClassCastException: org.apache.lucene.util.OpenBitSet cannot be cast to java.util.BitSet
|
||||
searcher.search(new MatchAllDocsQuery(), cf, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -991,11 +991,11 @@ final class DocumentsWriter {
|
|||
int limit = ((Integer) entry.getValue()).intValue();
|
||||
Weight weight = query.weight(searcher);
|
||||
Scorer scorer = weight.scorer(reader);
|
||||
while(scorer.next()) {
|
||||
final int docID = scorer.doc();
|
||||
if (docIDStart + docID >= limit)
|
||||
while(true) {
|
||||
int doc = scorer.nextDoc();
|
||||
if (((long) docIDStart) + doc >= limit)
|
||||
break;
|
||||
reader.deleteDocument(docID);
|
||||
reader.deleteDocument(doc);
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,13 +217,15 @@ public class BooleanQuery extends Query {
|
|||
}
|
||||
}
|
||||
|
||||
/** @return Returns BooleanScorer2 that uses and provides skipTo(),
|
||||
* and scores documents in document number order.
|
||||
/**
|
||||
* @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);
|
||||
|
|
|
@ -18,8 +18,11 @@ package org.apache.lucene.search;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
|
||||
/* Description from Doug Cutting (excerpted from
|
||||
* LUCENE-1483):
|
||||
*
|
||||
|
@ -54,30 +57,105 @@ import org.apache.lucene.index.IndexReader;
|
|||
* updates for the optional terms. */
|
||||
|
||||
final class BooleanScorer extends Scorer {
|
||||
private SubScorer scorers = null;
|
||||
private BucketTable bucketTable = new BucketTable();
|
||||
|
||||
private static final class BooleanScorerCollector extends Collector {
|
||||
private BucketTable bucketTable;
|
||||
private int mask;
|
||||
private Scorer scorer;
|
||||
|
||||
public BooleanScorerCollector(int mask, BucketTable bucketTable) {
|
||||
this.mask = mask;
|
||||
this.bucketTable = bucketTable;
|
||||
}
|
||||
public final void collect(final int doc) throws IOException {
|
||||
final BucketTable table = bucketTable;
|
||||
final int i = doc & BucketTable.MASK;
|
||||
Bucket bucket = table.buckets[i];
|
||||
if (bucket == null)
|
||||
table.buckets[i] = bucket = new Bucket();
|
||||
|
||||
if (bucket.doc != doc) { // invalid bucket
|
||||
bucket.doc = doc; // set doc
|
||||
bucket.score = scorer.score(); // initialize score
|
||||
bucket.bits = mask; // initialize mask
|
||||
bucket.coord = 1; // initialize coord
|
||||
|
||||
private int maxCoord = 1;
|
||||
private float[] coordFactors = null;
|
||||
|
||||
private int requiredMask = 0;
|
||||
private int prohibitedMask = 0;
|
||||
private int nextMask = 1;
|
||||
|
||||
private final int minNrShouldMatch;
|
||||
|
||||
BooleanScorer(Similarity similarity) {
|
||||
this(similarity, 1);
|
||||
bucket.next = table.first; // push onto valid list
|
||||
table.first = bucket;
|
||||
} else { // valid bucket
|
||||
bucket.score += scorer.score(); // increment score
|
||||
bucket.bits |= mask; // add bits in mask
|
||||
bucket.coord++; // increment coord
|
||||
}
|
||||
}
|
||||
|
||||
public void setNextReader(IndexReader reader, int docBase) {
|
||||
// not needed by this implementation
|
||||
}
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
this.scorer = scorer;
|
||||
}
|
||||
}
|
||||
|
||||
BooleanScorer(Similarity similarity, int minNrShouldMatch) {
|
||||
super(similarity);
|
||||
this.minNrShouldMatch = minNrShouldMatch;
|
||||
// An internal class which is used in score(Collector, int) for setting the
|
||||
// current score. This is required since Collector exposes a setScorer method
|
||||
// and implementations that need the score will call scorer.score().
|
||||
// Therefore the only methods that are implemented are score() and doc().
|
||||
private static final class BucketScorer extends Scorer {
|
||||
|
||||
float score;
|
||||
int doc = NO_MORE_DOCS;
|
||||
|
||||
public BucketScorer() { super(null); }
|
||||
|
||||
public int advance(int target) throws IOException { return NO_MORE_DOCS; }
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return doc; }
|
||||
|
||||
public int docID() { return doc; }
|
||||
|
||||
public Explanation explain(int doc) throws IOException { return null; }
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException { return false; }
|
||||
|
||||
public int nextDoc() throws IOException { return NO_MORE_DOCS; }
|
||||
|
||||
public float score() throws IOException { return score; }
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException { return false; }
|
||||
|
||||
}
|
||||
|
||||
static final class Bucket {
|
||||
int doc = -1; // tells if bucket is valid
|
||||
float score; // incremental score
|
||||
int bits; // used for bool constraints
|
||||
int coord; // count of terms in score
|
||||
Bucket next; // next valid bucket
|
||||
}
|
||||
|
||||
/** A simple hash table of document scores within a range. */
|
||||
static final class BucketTable {
|
||||
public static final int SIZE = 1 << 11;
|
||||
public static final int MASK = SIZE - 1;
|
||||
|
||||
final Bucket[] buckets = new Bucket[SIZE];
|
||||
Bucket first = null; // head of valid list
|
||||
|
||||
public BucketTable() {}
|
||||
|
||||
public Collector newCollector(int mask) {
|
||||
return new BooleanScorerCollector(mask, this);
|
||||
}
|
||||
|
||||
public final int size() { return SIZE; }
|
||||
}
|
||||
|
||||
static final class SubScorer {
|
||||
public Scorer scorer;
|
||||
public boolean done;
|
||||
public boolean required = false;
|
||||
public boolean prohibited = false;
|
||||
public Collector collector;
|
||||
|
@ -87,41 +165,52 @@ final class BooleanScorer extends Scorer {
|
|||
Collector collector, SubScorer next)
|
||||
throws IOException {
|
||||
this.scorer = scorer;
|
||||
this.done = !scorer.next();
|
||||
this.required = required;
|
||||
this.prohibited = prohibited;
|
||||
this.collector = collector;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
private SubScorer scorers = null;
|
||||
private BucketTable bucketTable = new BucketTable();
|
||||
private int maxCoord = 1;
|
||||
private final float[] coordFactors;
|
||||
private int requiredMask = 0;
|
||||
private int prohibitedMask = 0;
|
||||
private int nextMask = 1;
|
||||
private final int minNrShouldMatch;
|
||||
private int end;
|
||||
private Bucket current;
|
||||
private int doc = -1;
|
||||
|
||||
final void add(Scorer scorer, boolean required, boolean prohibited)
|
||||
throws IOException {
|
||||
int mask = 0;
|
||||
if (required || prohibited) {
|
||||
if (nextMask == 0) {
|
||||
throw new IndexOutOfBoundsException(
|
||||
"More than 32 required/prohibited clauses in query.");
|
||||
BooleanScorer(Similarity similarity, int minNrShouldMatch,
|
||||
List optionalScorers, List prohibitedScorers) throws IOException {
|
||||
super(similarity);
|
||||
this.minNrShouldMatch = minNrShouldMatch;
|
||||
|
||||
if (optionalScorers != null && optionalScorers.size() > 0) {
|
||||
for (Iterator si = optionalScorers.iterator(); si.hasNext();) {
|
||||
Scorer scorer = (Scorer) si.next();
|
||||
maxCoord++;
|
||||
if (scorer.nextDoc() != NO_MORE_DOCS) {
|
||||
scorers = new SubScorer(scorer, false, false, bucketTable.newCollector(0), scorers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prohibitedScorers != null && prohibitedScorers.size() > 0) {
|
||||
for (Iterator si = prohibitedScorers.iterator(); si.hasNext();) {
|
||||
Scorer scorer = (Scorer) si.next();
|
||||
int mask = nextMask;
|
||||
nextMask = nextMask << 1;
|
||||
prohibitedMask |= mask; // update prohibited mask
|
||||
if (scorer.nextDoc() != NO_MORE_DOCS) {
|
||||
scorers = new SubScorer(scorer, false, true, bucketTable.newCollector(mask), scorers);
|
||||
}
|
||||
}
|
||||
mask = nextMask;
|
||||
nextMask = nextMask << 1;
|
||||
}
|
||||
|
||||
if (!prohibited) {
|
||||
maxCoord++;
|
||||
if (required) {
|
||||
requiredMask |= mask; // update required mask
|
||||
}
|
||||
} else {
|
||||
// prohibited
|
||||
prohibitedMask |= mask; // update prohibited mask
|
||||
}
|
||||
|
||||
scorers = new SubScorer(scorer, required, prohibited,
|
||||
bucketTable.newCollector(mask), scorers);
|
||||
}
|
||||
|
||||
private final void computeCoordFactors() {
|
||||
coordFactors = new float[maxCoord];
|
||||
Similarity sim = getSimilarity();
|
||||
for (int i = 0; i < maxCoord; i++) {
|
||||
|
@ -129,31 +218,10 @@ final class BooleanScorer extends Scorer {
|
|||
}
|
||||
}
|
||||
|
||||
private int end;
|
||||
private Bucket current;
|
||||
|
||||
/** @deprecated use {@link #score(Collector)} instead. */
|
||||
public void score(HitCollector hc) throws IOException {
|
||||
score(new HitCollectorWrapper(hc));
|
||||
}
|
||||
|
||||
public void score(Collector collector) throws IOException {
|
||||
next();
|
||||
score(collector, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #score(Collector, int)} instead. */
|
||||
protected boolean score(HitCollector hc, int max) throws IOException {
|
||||
return score(new HitCollectorWrapper(hc), max);
|
||||
}
|
||||
|
||||
protected boolean score(Collector collector, int max) throws IOException {
|
||||
if (coordFactors == null) {
|
||||
computeCoordFactors();
|
||||
}
|
||||
// firstDocID is ignored since nextDoc() initializes 'current'
|
||||
protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
boolean more;
|
||||
Bucket tmp;
|
||||
|
||||
BucketScorer bs = new BucketScorer();
|
||||
// The internal loop will set the score and doc before calling collect.
|
||||
collector.setScorer(bs);
|
||||
|
@ -194,10 +262,9 @@ final class BooleanScorer extends Scorer {
|
|||
more = false;
|
||||
end += BucketTable.SIZE;
|
||||
for (SubScorer sub = scorers; sub != null; sub = sub.next) {
|
||||
if (!sub.done) {
|
||||
sub.done = !sub.scorer.score(sub.collector, end);
|
||||
if (!sub.done)
|
||||
more = true;
|
||||
int subScorerDocID = sub.scorer.docID();
|
||||
if (subScorerDocID != NO_MORE_DOCS) {
|
||||
more |= sub.scorer.score(sub.collector, end, subScorerDocID);
|
||||
}
|
||||
}
|
||||
current = bucketTable.first;
|
||||
|
@ -207,9 +274,32 @@ final class BooleanScorer extends Scorer {
|
|||
return false;
|
||||
}
|
||||
|
||||
public int doc() { return current.doc; }
|
||||
/** @deprecated use {@link #score(Collector, int)} instead. */
|
||||
protected boolean score(HitCollector hc, int max) throws IOException {
|
||||
return score(new HitCollectorWrapper(hc), max, docID());
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return current.doc; }
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
boolean more;
|
||||
do {
|
||||
while (bucketTable.first != null) { // more queued
|
||||
|
@ -220,7 +310,7 @@ final class BooleanScorer extends Scorer {
|
|||
if ((current.bits & prohibitedMask) == 0 &&
|
||||
(current.bits & requiredMask) == requiredMask &&
|
||||
current.coord >= minNrShouldMatch) {
|
||||
return true;
|
||||
return doc = current.doc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,134 +320,36 @@ final class BooleanScorer extends Scorer {
|
|||
for (SubScorer sub = scorers; sub != null; sub = sub.next) {
|
||||
Scorer scorer = sub.scorer;
|
||||
sub.collector.setScorer(scorer);
|
||||
while (!sub.done && scorer.doc() < end) {
|
||||
sub.collector.collect(scorer.doc());
|
||||
sub.done = !scorer.next();
|
||||
}
|
||||
if (!sub.done) {
|
||||
more = true;
|
||||
int doc = scorer.docID();
|
||||
while (doc < end) {
|
||||
sub.collector.collect(doc);
|
||||
doc = scorer.nextDoc();
|
||||
}
|
||||
more |= (doc != NO_MORE_DOCS);
|
||||
}
|
||||
} while (bucketTable.first != null || more);
|
||||
|
||||
return false;
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public float score() {
|
||||
if (coordFactors == null) {
|
||||
computeCoordFactors();
|
||||
}
|
||||
return current.score * coordFactors[current.coord];
|
||||
}
|
||||
|
||||
static final class Bucket {
|
||||
int doc = -1; // tells if bucket is valid
|
||||
float score; // incremental score
|
||||
int bits; // used for bool constraints
|
||||
int coord; // count of terms in score
|
||||
Bucket next; // next valid bucket
|
||||
public void score(Collector collector) throws IOException {
|
||||
score(collector, Integer.MAX_VALUE, nextDoc());
|
||||
}
|
||||
|
||||
// An internal class which is used in score(Collector, int) for setting the
|
||||
// current score. This is required since Collector exposes a setScorer method
|
||||
// and implementations that need the score will call scorer.score().
|
||||
// Therefore the only methods that are implemented are score() and doc().
|
||||
private static final class BucketScorer extends Scorer {
|
||||
|
||||
float score;
|
||||
int doc;
|
||||
|
||||
public BucketScorer() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public float score() throws IOException {
|
||||
return score;
|
||||
}
|
||||
|
||||
public int doc() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public boolean next() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #score(Collector)} instead. */
|
||||
public void score(HitCollector hc) throws IOException {
|
||||
score(new HitCollectorWrapper(hc));
|
||||
}
|
||||
|
||||
/** A simple hash table of document scores within a range. */
|
||||
static final class BucketTable {
|
||||
public static final int SIZE = 1 << 11;
|
||||
public static final int MASK = SIZE - 1;
|
||||
|
||||
final Bucket[] buckets = new Bucket[SIZE];
|
||||
Bucket first = null; // head of valid list
|
||||
|
||||
public BucketTable() {}
|
||||
|
||||
public final int size() { return SIZE; }
|
||||
|
||||
public Collector newCollector(int mask) {
|
||||
return new BooleanScorerCollector(mask, this);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BooleanScorerCollector extends Collector {
|
||||
private BucketTable bucketTable;
|
||||
private int mask;
|
||||
private Scorer scorer;
|
||||
|
||||
public BooleanScorerCollector(int mask, BucketTable bucketTable) {
|
||||
this.mask = mask;
|
||||
this.bucketTable = bucketTable;
|
||||
}
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
this.scorer = scorer;
|
||||
}
|
||||
|
||||
public final void collect(final int doc) throws IOException {
|
||||
final BucketTable table = bucketTable;
|
||||
final int i = doc & BucketTable.MASK;
|
||||
Bucket bucket = table.buckets[i];
|
||||
if (bucket == null)
|
||||
table.buckets[i] = bucket = new Bucket();
|
||||
|
||||
if (bucket.doc != doc) { // invalid bucket
|
||||
bucket.doc = doc; // set doc
|
||||
bucket.score = scorer.score(); // initialize score
|
||||
bucket.bits = mask; // initialize mask
|
||||
bucket.coord = 1; // initialize coord
|
||||
|
||||
bucket.next = table.first; // push onto valid list
|
||||
table.first = bucket;
|
||||
} else { // valid bucket
|
||||
bucket.score += scorer.score(); // increment score
|
||||
bucket.bits |= mask; // add bits in mask
|
||||
bucket.coord++; // increment coord
|
||||
}
|
||||
}
|
||||
public void setNextReader(IndexReader reader, int docBase) {
|
||||
// not needed by this implementation
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("boolean(");
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.lucene.search;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
|
||||
/* See the description in BooleanScorer.java, comparing
|
||||
* BooleanScorer & BooleanScorer2 */
|
||||
|
@ -65,6 +64,7 @@ class BooleanScorer2 extends Scorer {
|
|||
*/
|
||||
private boolean allowDocsOutOfOrder;
|
||||
|
||||
private int doc = -1;
|
||||
|
||||
/** Create a BooleanScorer2.
|
||||
* @param similarity The similarity to be used.
|
||||
|
@ -151,7 +151,7 @@ class BooleanScorer2 extends Scorer {
|
|||
this.scorer = scorer;
|
||||
}
|
||||
public float score() throws IOException {
|
||||
int doc = doc();
|
||||
int doc = docID();
|
||||
if (doc >= lastScoredDoc) {
|
||||
if (doc > lastScoredDoc) {
|
||||
lastDocScore = scorer.score();
|
||||
|
@ -161,14 +161,26 @@ class BooleanScorer2 extends Scorer {
|
|||
}
|
||||
return lastDocScore;
|
||||
}
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return scorer.doc();
|
||||
}
|
||||
public boolean next() throws IOException {
|
||||
return scorer.next();
|
||||
public int docID() {
|
||||
return scorer.docID();
|
||||
}
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return scorer.nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
public int nextDoc() throws IOException {
|
||||
return scorer.nextDoc();
|
||||
}
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int docNr) throws IOException {
|
||||
return scorer.skipTo(docNr);
|
||||
return scorer.advance(docNr) != NO_MORE_DOCS;
|
||||
}
|
||||
public int advance(int target) throws IOException {
|
||||
return scorer.advance(target);
|
||||
}
|
||||
public Explanation explain(int docNr) throws IOException {
|
||||
return scorer.explain(docNr);
|
||||
|
@ -184,7 +196,7 @@ class BooleanScorer2 extends Scorer {
|
|||
// once in score().
|
||||
private float lastDocScore = Float.NaN;
|
||||
public float score() throws IOException {
|
||||
int doc = doc();
|
||||
int doc = docID();
|
||||
if (doc >= lastScoredDoc) {
|
||||
if (doc > lastScoredDoc) {
|
||||
lastDocScore = super.score();
|
||||
|
@ -208,7 +220,7 @@ class BooleanScorer2 extends Scorer {
|
|||
// once in score().
|
||||
private float lastDocScore = Float.NaN;
|
||||
public float score() throws IOException {
|
||||
int doc = doc();
|
||||
int doc = docID();
|
||||
if (doc >= lastScoredDoc) {
|
||||
if (doc > lastScoredDoc) {
|
||||
lastDocScore = super.score();
|
||||
|
@ -323,24 +335,16 @@ class BooleanScorer2 extends Scorer {
|
|||
public void score(Collector collector) throws IOException {
|
||||
if (allowDocsOutOfOrder && requiredScorers.size() == 0
|
||||
&& prohibitedScorers.size() < 32) {
|
||||
// fall back to BooleanScorer, scores documents somewhat out of order
|
||||
BooleanScorer bs = new BooleanScorer(getSimilarity(), minNrShouldMatch);
|
||||
Iterator si = optionalScorers.iterator();
|
||||
while (si.hasNext()) {
|
||||
bs.add((Scorer) si.next(), false /* required */, false /* prohibited */);
|
||||
}
|
||||
si = prohibitedScorers.iterator();
|
||||
while (si.hasNext()) {
|
||||
bs.add((Scorer) si.next(), false /* required */, true /* prohibited */);
|
||||
}
|
||||
bs.score(collector);
|
||||
new BooleanScorer(getSimilarity(), minNrShouldMatch, optionalScorers,
|
||||
prohibitedScorers).score(collector);
|
||||
} else {
|
||||
if (countingSumScorer == null) {
|
||||
initCountingSumScorer();
|
||||
}
|
||||
collector.setScorer(this);
|
||||
while (countingSumScorer.next()) {
|
||||
collector.collect(countingSumScorer.doc());
|
||||
int doc;
|
||||
while ((doc = countingSumScorer.nextDoc()) != NO_MORE_DOCS) {
|
||||
collector.collect(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -355,60 +359,57 @@ class BooleanScorer2 extends Scorer {
|
|||
* @deprecated use {@link #score(Collector, int)} instead.
|
||||
*/
|
||||
protected boolean score(HitCollector hc, int max) throws IOException {
|
||||
return score(new HitCollectorWrapper(hc), max);
|
||||
return score(new HitCollectorWrapper(hc), max, docID());
|
||||
}
|
||||
|
||||
/** Expert: Collects matching documents in a range.
|
||||
* <br>Note that {@link #next()} must be called once before this method is
|
||||
* called for the first time.
|
||||
* @param collector The collector to which all matching documents are passed through.
|
||||
* @param max Do not score documents past this.
|
||||
* @return true if more matching documents may remain.
|
||||
*/
|
||||
protected boolean score(Collector collector, int max) throws IOException {
|
||||
protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
// null pointer exception when next() was not called before:
|
||||
int docNr = countingSumScorer.doc();
|
||||
int docNr = firstDocID;
|
||||
collector.setScorer(this);
|
||||
while (docNr < max) {
|
||||
collector.collect(docNr);
|
||||
if (!countingSumScorer.next()) {
|
||||
return false;
|
||||
}
|
||||
docNr = countingSumScorer.doc();
|
||||
docNr = countingSumScorer.nextDoc();
|
||||
}
|
||||
return true;
|
||||
return docNr != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return countingSumScorer.doc(); }
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
if (countingSumScorer == null) {
|
||||
initCountingSumScorer();
|
||||
}
|
||||
return countingSumScorer.next();
|
||||
return doc = countingSumScorer.nextDoc();
|
||||
}
|
||||
|
||||
|
||||
public float score() throws IOException {
|
||||
coordinator.nrMatchers = 0;
|
||||
float sum = countingSumScorer.score();
|
||||
return sum * coordinator.coordFactors[coordinator.nrMatchers];
|
||||
}
|
||||
|
||||
/** Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target.
|
||||
*
|
||||
* <p>When this method is used the {@link #explain(int)} method should not be used.
|
||||
*
|
||||
* @param target The target document number.
|
||||
* @return true iff there is such a match.
|
||||
*/
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
if (countingSumScorer == null) {
|
||||
initCountingSumScorer();
|
||||
}
|
||||
return countingSumScorer.skipTo(target);
|
||||
return doc = countingSumScorer.advance(target);
|
||||
}
|
||||
|
||||
|
||||
/** Throws an UnsupportedOperationException.
|
||||
* TODO: Implement an explanation of the coordination factor.
|
||||
* @param doc The document number for the explanation.
|
||||
|
|
|
@ -24,76 +24,54 @@ import java.util.Comparator;
|
|||
|
||||
/** Scorer for conjunctions, sets of queries, all of which are required. */
|
||||
class ConjunctionScorer extends Scorer {
|
||||
|
||||
private final Scorer[] scorers;
|
||||
|
||||
private boolean firstTime=true;
|
||||
private boolean more;
|
||||
private final float coord;
|
||||
private int lastDoc=-1;
|
||||
private int lastDoc = -1;
|
||||
|
||||
public ConjunctionScorer(Similarity similarity, Collection scorers) throws IOException {
|
||||
this(similarity, (Scorer[])scorers.toArray(new Scorer[scorers.size()]));
|
||||
this(similarity, (Scorer[]) scorers.toArray(new Scorer[scorers.size()]));
|
||||
}
|
||||
|
||||
public ConjunctionScorer(Similarity similarity, Scorer[] scorers) throws IOException {
|
||||
super(similarity);
|
||||
this.scorers = scorers;
|
||||
coord = getSimilarity().coord(this.scorers.length, this.scorers.length);
|
||||
}
|
||||
|
||||
public int doc() { return lastDoc; }
|
||||
|
||||
public boolean next() throws IOException {
|
||||
if (firstTime)
|
||||
return init(0);
|
||||
else if (more)
|
||||
more = scorers[(scorers.length-1)].next();
|
||||
return doNext();
|
||||
}
|
||||
|
||||
private boolean doNext() throws IOException {
|
||||
int first=0;
|
||||
Scorer lastScorer = scorers[scorers.length-1];
|
||||
Scorer firstScorer;
|
||||
while (more && (firstScorer=scorers[first]).doc() < (lastDoc=lastScorer.doc())) {
|
||||
more = firstScorer.skipTo(lastDoc);
|
||||
lastScorer = firstScorer;
|
||||
first = (first == (scorers.length-1)) ? 0 : first+1;
|
||||
}
|
||||
return more;
|
||||
}
|
||||
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (firstTime)
|
||||
return init(target);
|
||||
else if (more)
|
||||
more = scorers[(scorers.length-1)].skipTo(target);
|
||||
return doNext();
|
||||
}
|
||||
|
||||
// Note... most of this could be done in the constructor
|
||||
// thus skipping a check for firstTime per call to next() and skipTo()
|
||||
private boolean init(int target) throws IOException {
|
||||
firstTime=false;
|
||||
more = scorers.length>1;
|
||||
for (int i=0; i<scorers.length; i++) {
|
||||
more = target==0 ? scorers[i].next() : scorers[i].skipTo(target);
|
||||
if (!more)
|
||||
return false;
|
||||
coord = similarity.coord(scorers.length, scorers.length);
|
||||
|
||||
for (int i = 0; i < scorers.length; i++) {
|
||||
if (scorers[i].nextDoc() == NO_MORE_DOCS) {
|
||||
// If even one of the sub-scorers does not have any documents, this
|
||||
// scorer should not attempt to do any more work.
|
||||
lastDoc = NO_MORE_DOCS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the array the first time...
|
||||
// We don't need to sort the array in any future calls because we know
|
||||
// it will already start off sorted (all scorers on same doc).
|
||||
|
||||
|
||||
// note that this comparator is not consistent with equals!
|
||||
Arrays.sort(scorers, new Comparator() { // sort the array
|
||||
public int compare(Object o1, Object o2) {
|
||||
return ((Scorer)o1).doc() - ((Scorer)o2).doc();
|
||||
}
|
||||
});
|
||||
public int compare(Object o1, Object o2) {
|
||||
return ((Scorer) o1).docID() - ((Scorer) o2).docID();
|
||||
}
|
||||
});
|
||||
|
||||
doNext();
|
||||
// NOTE: doNext() must be called before the re-sorting of the array later on.
|
||||
// The reason is this: assume there are 5 scorers, whose first docs are 1,
|
||||
// 2, 3, 5, 5 respectively. Sorting (above) leaves the array as is. Calling
|
||||
// doNext() here advances all the first scorers to 5 (or a larger doc ID
|
||||
// they all agree on).
|
||||
// However, if we re-sort before doNext() is called, the order will be 5, 3,
|
||||
// 2, 1, 5 and then doNext() will stop immediately, since the first scorer's
|
||||
// docs equals the last one. So the invariant that after calling doNext()
|
||||
// all scorers are on the same doc ID is broken.
|
||||
if (doNext() == NO_MORE_DOCS) {
|
||||
// The scorers did not agree on any document.
|
||||
lastDoc = NO_MORE_DOCS;
|
||||
return;
|
||||
}
|
||||
|
||||
// If first-time skip distance is any predictor of
|
||||
// scorer sparseness, then we should always try to skip first on
|
||||
|
@ -101,16 +79,62 @@ class ConjunctionScorer extends Scorer {
|
|||
// Keep last scorer in it's last place (it will be the first
|
||||
// to be skipped on), but reverse all of the others so that
|
||||
// they will be skipped on in order of original high skip.
|
||||
int end=(scorers.length-1);
|
||||
for (int i=0; i<(end>>1); i++) {
|
||||
int end = scorers.length - 1;
|
||||
int max = end >> 1;
|
||||
for (int i = 0; i < max; i++) {
|
||||
Scorer tmp = scorers[i];
|
||||
scorers[i] = scorers[end-i-1];
|
||||
scorers[end-i-1] = tmp;
|
||||
int idx = end - i - 1;
|
||||
scorers[i] = scorers[idx];
|
||||
scorers[idx] = tmp;
|
||||
}
|
||||
|
||||
return more;
|
||||
}
|
||||
|
||||
private int doNext() throws IOException {
|
||||
int first = 0;
|
||||
int doc = scorers[scorers.length - 1].docID();
|
||||
Scorer firstScorer;
|
||||
while ((firstScorer = scorers[first]).docID() < doc) {
|
||||
doc = firstScorer.advance(doc);
|
||||
first = first == scorers.length - 1 ? 0 : first + 1;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
if (lastDoc == NO_MORE_DOCS) {
|
||||
return lastDoc;
|
||||
} else if (scorers[(scorers.length - 1)].docID() < target) {
|
||||
scorers[(scorers.length - 1)].advance(target);
|
||||
}
|
||||
return lastDoc = doNext();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return lastDoc; }
|
||||
|
||||
public int docID() {
|
||||
return lastDoc;
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
if (lastDoc == NO_MORE_DOCS) {
|
||||
return lastDoc;
|
||||
} else if (lastDoc == -1) {
|
||||
return lastDoc = scorers[scorers.length - 1].docID();
|
||||
}
|
||||
scorers[(scorers.length - 1)].nextDoc();
|
||||
return lastDoc = doNext();
|
||||
}
|
||||
|
||||
public float score() throws IOException {
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < scorers.length; i++) {
|
||||
|
@ -119,8 +143,9 @@ class ConjunctionScorer extends Scorer {
|
|||
return sum * coord;
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) {
|
||||
throw new UnsupportedOperationException();
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public class ConstantScoreQuery extends Query {
|
|||
public Explanation explain(IndexReader reader, int doc) throws IOException {
|
||||
|
||||
ConstantScorer cs = (ConstantScorer)scorer(reader);
|
||||
boolean exists = cs.docIdSetIterator.skipTo(doc) && (cs.docIdSetIterator.doc() == doc);
|
||||
boolean exists = cs.docIdSetIterator.advance(doc) == doc;
|
||||
|
||||
ComplexExplanation result = new ComplexExplanation();
|
||||
|
||||
|
@ -108,7 +108,7 @@ public class ConstantScoreQuery extends Query {
|
|||
protected class ConstantScorer extends Scorer {
|
||||
final DocIdSetIterator docIdSetIterator;
|
||||
final float theScore;
|
||||
int doc=-1;
|
||||
int doc = -1;
|
||||
|
||||
public ConstantScorer(Similarity similarity, IndexReader reader, Weight w) throws IOException {
|
||||
super(similarity);
|
||||
|
@ -116,36 +116,48 @@ public class ConstantScoreQuery extends Query {
|
|||
docIdSetIterator = filter.getDocIdSet(reader).iterator();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return docIdSetIterator.next();
|
||||
return docIdSetIterator.nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return docIdSetIterator.nextDoc();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return docIdSetIterator.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return docIdSetIterator.docID();
|
||||
}
|
||||
|
||||
public float score() throws IOException {
|
||||
return theScore;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return docIdSetIterator.skipTo(target);
|
||||
return docIdSetIterator.advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return docIdSetIterator.advance(target);
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Weight createWeight(Searcher searcher) {
|
||||
return new ConstantScoreQuery.ConstantWeight(searcher);
|
||||
}
|
||||
|
||||
|
||||
/** Prints a user-readable version of this query. */
|
||||
public String toString(String field)
|
||||
{
|
||||
public String toString(String field) {
|
||||
return "ConstantScore(" + filter.toString()
|
||||
+ (getBoost()==1.0 ? ")" : "^" + getBoost());
|
||||
}
|
||||
|
@ -165,6 +177,3 @@ public class ConstantScoreQuery extends Query {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,14 +16,14 @@ package org.apache.lucene.search;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
|
||||
/**
|
||||
* A query that generates the union of documents produced by its subqueries, and that scores each document with the maximum
|
||||
* score for that document as produced by any subquery, plus a tie breaking increment for any additional matching subqueries.
|
||||
|
@ -124,13 +124,19 @@ public class DisjunctionMaxQuery extends Query {
|
|||
|
||||
/* Create the scorer used to score our associated DisjunctionMaxQuery */
|
||||
public Scorer scorer(IndexReader reader) throws IOException {
|
||||
DisjunctionMaxScorer result = new DisjunctionMaxScorer(tieBreakerMultiplier, similarity);
|
||||
for (int i = 0 ; i < weights.size(); i++) {
|
||||
Weight w = (Weight) weights.get(i);
|
||||
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);
|
||||
if (subScorer == null) return null;
|
||||
result.add(subScorer);
|
||||
if (subScorer == null) {
|
||||
return null;
|
||||
} else if (subScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
scorers[idx++] = subScorer;
|
||||
}
|
||||
}
|
||||
if (idx == 0) return null; // all scorers did not have documents
|
||||
DisjunctionMaxScorer result = new DisjunctionMaxScorer(tieBreakerMultiplier, similarity, scorers, idx);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ package org.apache.lucene.search;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The Scorer for DisjunctionMaxQuery's. The union of all documents generated by the the subquery scorers
|
||||
|
@ -27,168 +26,192 @@ import java.util.ArrayList;
|
|||
*/
|
||||
class DisjunctionMaxScorer extends Scorer {
|
||||
|
||||
/* The scorers for subqueries that have remaining docs, kept as a min heap by number of next doc. */
|
||||
private ArrayList subScorers = new ArrayList();
|
||||
/* The scorers for subqueries that have remaining docs, kept as a min heap by number of next doc. */
|
||||
private final Scorer[] subScorers;
|
||||
private int numScorers;
|
||||
/* Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. */
|
||||
private final float tieBreakerMultiplier;
|
||||
private int doc = -1;
|
||||
|
||||
/* Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. */
|
||||
private float tieBreakerMultiplier;
|
||||
/**
|
||||
* Creates a new instance of DisjunctionMaxScorer
|
||||
*
|
||||
* @param tieBreakerMultiplier
|
||||
* Multiplier applied to non-maximum-scoring subqueries for a
|
||||
* document as they are summed into the result.
|
||||
* @param similarity
|
||||
* -- not used since our definition involves neither coord nor terms
|
||||
* directly
|
||||
* @param subScorers
|
||||
* The sub scorers this Scorer should iterate on
|
||||
* @param numScorers
|
||||
* The actual number of scorers to iterate on. Note that the array's
|
||||
* length may be larger than the actual number of scorers.
|
||||
*/
|
||||
public DisjunctionMaxScorer(float tieBreakerMultiplier,
|
||||
Similarity similarity, Scorer[] subScorers, int numScorers) throws IOException {
|
||||
super(similarity);
|
||||
|
||||
private boolean more = false; // True iff there is a next document
|
||||
private boolean firstTime = true; // True iff next() has not yet been called
|
||||
this.tieBreakerMultiplier = tieBreakerMultiplier;
|
||||
// The passed subScorers array includes only scorers which have documents
|
||||
// (DisjunctionMaxQuery takes care of that), and their nextDoc() was already
|
||||
// called.
|
||||
this.subScorers = subScorers;
|
||||
this.numScorers = numScorers;
|
||||
|
||||
heapify();
|
||||
}
|
||||
|
||||
/** Creates a new instance of DisjunctionMaxScorer
|
||||
* @param tieBreakerMultiplier Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result.
|
||||
* @param similarity -- not used since our definition involves neither coord nor terms directly */
|
||||
public DisjunctionMaxScorer(float tieBreakerMultiplier, Similarity similarity) {
|
||||
super(similarity);
|
||||
this.tieBreakerMultiplier = tieBreakerMultiplier;
|
||||
}
|
||||
/**
|
||||
* Generate the next document matching our associated DisjunctionMaxQuery.
|
||||
*
|
||||
* @return true iff there is a next document
|
||||
* @deprecated use {@link #nextDoc()} instead.
|
||||
*/
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** Add the scorer for a subquery
|
||||
* @param scorer the scorer of a subquery of our associated DisjunctionMaxQuery
|
||||
*/
|
||||
public void add(Scorer scorer) throws IOException {
|
||||
if (scorer.next()) { // Initialize and retain only if it produces docs
|
||||
subScorers.add(scorer);
|
||||
more = true;
|
||||
public int nextDoc() throws IOException {
|
||||
if (numScorers == 0) return doc = NO_MORE_DOCS;
|
||||
while (subScorers[0].docID() == doc) {
|
||||
if (subScorers[0].nextDoc() != NO_MORE_DOCS) {
|
||||
heapAdjust(0);
|
||||
} else {
|
||||
heapRemoveRoot();
|
||||
if (numScorers == 0) {
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doc = subScorers[0].docID();
|
||||
}
|
||||
|
||||
/** Generate the next document matching our associated DisjunctionMaxQuery.
|
||||
* @return true iff there is a next document
|
||||
*/
|
||||
public boolean next() throws IOException {
|
||||
if (!more) return false;
|
||||
if (firstTime) {
|
||||
heapify();
|
||||
firstTime = false;
|
||||
return true; // more would have been false if no subScorers had any docs
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return subScorers[0].doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** Determine the current document score. Initially invalid, until {@link #next()} is called the first time.
|
||||
* @return the score of the current generated document
|
||||
*/
|
||||
public float score() throws IOException {
|
||||
int doc = subScorers[0].docID();
|
||||
float[] sum = { subScorers[0].score() }, max = { sum[0] };
|
||||
int size = numScorers;
|
||||
scoreAll(1, size, doc, sum, max);
|
||||
scoreAll(2, size, doc, sum, max);
|
||||
return max[0] + (sum[0] - max[0]) * tieBreakerMultiplier;
|
||||
}
|
||||
|
||||
// Recursively iterate all subScorers that generated last doc computing sum and max
|
||||
private void scoreAll(int root, int size, int doc, float[] sum, float[] max) throws IOException {
|
||||
if (root < size && subScorers[root].docID() == doc) {
|
||||
float sub = subScorers[root].score();
|
||||
sum[0] += sub;
|
||||
max[0] = Math.max(max[0], sub);
|
||||
scoreAll((root<<1)+1, size, doc, sum, max);
|
||||
scoreAll((root<<1)+2, size, doc, sum, max);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance to the first document beyond the current whose number is greater
|
||||
* than or equal to target.
|
||||
*
|
||||
* @param target
|
||||
* the minimum number of the next desired document
|
||||
* @return true iff there is a document to be generated whose number is at
|
||||
* least target
|
||||
* @deprecated use {@link #advance(int)} instead.
|
||||
*/
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
if (numScorers == 0) return doc = NO_MORE_DOCS;
|
||||
while (subScorers[0].docID() < target) {
|
||||
if (subScorers[0].advance(target) != NO_MORE_DOCS) {
|
||||
heapAdjust(0);
|
||||
} else {
|
||||
heapRemoveRoot();
|
||||
if (numScorers == 0) {
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
// Increment all generators that generated the last doc and adjust the heap.
|
||||
int lastdoc = ((Scorer) subScorers.get(0)).doc();
|
||||
do {
|
||||
if (((Scorer) subScorers.get(0)).next())
|
||||
heapAdjust(0);
|
||||
else {
|
||||
heapRemoveRoot();
|
||||
if (subScorers.isEmpty()) return (more = false);
|
||||
}
|
||||
} while ( ((Scorer) subScorers.get(0)).doc()==lastdoc );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return doc = subScorers[0].docID();
|
||||
}
|
||||
|
||||
/** Determine the current document number. Initially invalid, until {@link #next()} is called the first time.
|
||||
* @return the document number of the currently generated document
|
||||
*/
|
||||
public int doc() {
|
||||
return ((Scorer) subScorers.get(0)).doc();
|
||||
/** Explain a score that we computed. UNSUPPORTED -- see explanation capability in DisjunctionMaxQuery.
|
||||
* @param doc the number of a document we scored
|
||||
* @return the Explanation for our score
|
||||
*/
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// Organize subScorers into a min heap with scorers generating the earliest document on top.
|
||||
private void heapify() {
|
||||
for (int i = (numScorers >> 1) - 1; i >= 0; i--) {
|
||||
heapAdjust(i);
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine the current document score. Initially invalid, until {@link #next()} is called the first time.
|
||||
* @return the score of the current generated document
|
||||
*/
|
||||
public float score() throws IOException {
|
||||
int doc = ((Scorer) subScorers.get(0)).doc();
|
||||
float[] sum = {((Scorer) subScorers.get(0)).score()}, max = {sum[0]};
|
||||
int size = subScorers.size();
|
||||
scoreAll(1, size, doc, sum, max);
|
||||
scoreAll(2, size, doc, sum, max);
|
||||
return max[0] + (sum[0] - max[0])*tieBreakerMultiplier;
|
||||
}
|
||||
|
||||
// Recursively iterate all subScorers that generated last doc computing sum and max
|
||||
private void scoreAll(int root, int size, int doc, float[] sum, float[] max) throws IOException {
|
||||
if (root<size && ((Scorer) subScorers.get(root)).doc() == doc) {
|
||||
float sub = ((Scorer) subScorers.get(root)).score();
|
||||
sum[0] += sub;
|
||||
max[0] = Math.max(max[0], sub);
|
||||
scoreAll((root<<1)+1, size, doc, sum, max);
|
||||
scoreAll((root<<1)+2, size, doc, sum, max);
|
||||
/* The subtree of subScorers at root is a min heap except possibly for its root element.
|
||||
* Bubble the root down as required to make the subtree a heap.
|
||||
*/
|
||||
private void heapAdjust(int root) {
|
||||
Scorer scorer = subScorers[root];
|
||||
int doc = scorer.docID();
|
||||
int i = root;
|
||||
while (i <= (numScorers >> 1) - 1) {
|
||||
int lchild = (i << 1) + 1;
|
||||
Scorer lscorer = subScorers[lchild];
|
||||
int ldoc = lscorer.docID();
|
||||
int rdoc = Integer.MAX_VALUE, rchild = (i << 1) + 2;
|
||||
Scorer rscorer = null;
|
||||
if (rchild < numScorers) {
|
||||
rscorer = subScorers[rchild];
|
||||
rdoc = rscorer.docID();
|
||||
}
|
||||
if (ldoc < doc) {
|
||||
if (rdoc < ldoc) {
|
||||
subScorers[i] = rscorer;
|
||||
subScorers[rchild] = scorer;
|
||||
i = rchild;
|
||||
} else {
|
||||
subScorers[i] = lscorer;
|
||||
subScorers[lchild] = scorer;
|
||||
i = lchild;
|
||||
}
|
||||
} else if (rdoc < doc) {
|
||||
subScorers[i] = rscorer;
|
||||
subScorers[rchild] = scorer;
|
||||
i = rchild;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Advance to the first document beyond the current whose number is greater than or equal to target.
|
||||
* @param target the minimum number of the next desired document
|
||||
* @return true iff there is a document to be generated whose number is at least target
|
||||
*/
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (firstTime) {
|
||||
if (!more) return false;
|
||||
heapify();
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
while (subScorers.size()>0 && ((Scorer)subScorers.get(0)).doc()<target) {
|
||||
if (((Scorer)subScorers.get(0)).skipTo(target))
|
||||
heapAdjust(0);
|
||||
else
|
||||
heapRemoveRoot();
|
||||
}
|
||||
if ((subScorers.size()==0))
|
||||
return (more = false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Explain a score that we computed. UNSUPPORTED -- see explanation capability in DisjunctionMaxQuery.
|
||||
* @param doc the number of a document we scored
|
||||
* @return the Explanation for our score
|
||||
*/
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// Organize subScorers into a min heap with scorers generating the earlest document on top.
|
||||
private void heapify() {
|
||||
int size = subScorers.size();
|
||||
for (int i=(size>>1)-1; i>=0; i--)
|
||||
heapAdjust(i);
|
||||
}
|
||||
|
||||
/* The subtree of subScorers at root is a min heap except possibly for its root element.
|
||||
* Bubble the root down as required to make the subtree a heap.
|
||||
*/
|
||||
private void heapAdjust(int root) {
|
||||
Scorer scorer=(Scorer)subScorers.get(root);
|
||||
int doc=scorer.doc();
|
||||
int i=root, size=subScorers.size();
|
||||
while (i<=(size>>1)-1) {
|
||||
int lchild=(i<<1)+1;
|
||||
Scorer lscorer=(Scorer)subScorers.get(lchild);
|
||||
int ldoc=lscorer.doc();
|
||||
int rdoc=Integer.MAX_VALUE, rchild=(i<<1)+2;
|
||||
Scorer rscorer=null;
|
||||
if (rchild<size) {
|
||||
rscorer=(Scorer)subScorers.get(rchild);
|
||||
rdoc=rscorer.doc();
|
||||
}
|
||||
if (ldoc<doc) {
|
||||
if (rdoc<ldoc) {
|
||||
subScorers.set(i, rscorer);
|
||||
subScorers.set(rchild, scorer);
|
||||
i=rchild;
|
||||
} else {
|
||||
subScorers.set(i, lscorer);
|
||||
subScorers.set(lchild, scorer);
|
||||
i=lchild;
|
||||
}
|
||||
} else if (rdoc<doc) {
|
||||
subScorers.set(i, rscorer);
|
||||
subScorers.set(rchild, scorer);
|
||||
i=rchild;
|
||||
} else return;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the root Scorer from subScorers and re-establish it as a heap
|
||||
private void heapRemoveRoot() {
|
||||
int size=subScorers.size();
|
||||
if (size==1)
|
||||
subScorers.remove(0);
|
||||
else {
|
||||
subScorers.set(0, subScorers.get(size-1));
|
||||
subScorers.remove(size-1);
|
||||
heapAdjust(0);
|
||||
}
|
||||
// Remove the root Scorer from subScorers and re-establish it as a heap
|
||||
private void heapRemoveRoot() {
|
||||
if (numScorers == 1) {
|
||||
subScorers[0] = null;
|
||||
numScorers = 0;
|
||||
} else {
|
||||
subScorers[0] = subScorers[numScorers - 1];
|
||||
subScorers[numScorers - 1] = null;
|
||||
--numScorers;
|
||||
heapAdjust(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ class DisjunctionSumScorer extends Scorer {
|
|||
scorerDocQueue = new ScorerDocQueue(nrScorers);
|
||||
while (si.hasNext()) {
|
||||
Scorer se = (Scorer) si.next();
|
||||
if (se.next()) { // doc() method will be used in scorerDocQueue.
|
||||
if (se.nextDoc() != NO_MORE_DOCS) { // doc() method will be used in scorerDocQueue.
|
||||
scorerDocQueue.insert(se);
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ class DisjunctionSumScorer extends Scorer {
|
|||
*/
|
||||
public void score(Collector collector) throws IOException {
|
||||
collector.setScorer(this);
|
||||
while (next()) {
|
||||
while (nextDoc() != NO_MORE_DOCS) {
|
||||
collector.collect(currentDoc);
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ class DisjunctionSumScorer extends Scorer {
|
|||
* @deprecated use {@link #score(Collector, int)} instead.
|
||||
*/
|
||||
protected boolean score(HitCollector hc, int max) throws IOException {
|
||||
return score(new HitCollectorWrapper(hc), max);
|
||||
return score(new HitCollectorWrapper(hc), max, docID());
|
||||
}
|
||||
|
||||
/** Expert: Collects matching documents in a range. Hook for optimization.
|
||||
|
@ -149,22 +149,29 @@ class DisjunctionSumScorer extends Scorer {
|
|||
* @param max Do not score documents past this.
|
||||
* @return true if more matching documents may remain.
|
||||
*/
|
||||
protected boolean score(Collector collector, int max) throws IOException {
|
||||
protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
// firstDocID is ignored since nextDoc() sets 'currentDoc'
|
||||
collector.setScorer(this);
|
||||
while (currentDoc < max) {
|
||||
collector.collect(currentDoc);
|
||||
if (!next()) {
|
||||
if (nextDoc() == NO_MORE_DOCS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return (scorerDocQueue.size() >= minimumNrMatchers)
|
||||
&& advanceAfterCurrent();
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
if (scorerDocQueue.size() < minimumNrMatchers || !advanceAfterCurrent()) {
|
||||
currentDoc = NO_MORE_DOCS;
|
||||
}
|
||||
return currentDoc;
|
||||
}
|
||||
|
||||
/** Advance all subscorers after the current document determined by the
|
||||
* top of the <code>scorerDocQueue</code>.
|
||||
|
@ -176,7 +183,7 @@ class DisjunctionSumScorer extends Scorer {
|
|||
* <br>In case there is a match, </code>currentDoc</code>, </code>currentSumScore</code>,
|
||||
* and </code>nrMatchers</code> describe the match.
|
||||
*
|
||||
* @todo Investigate whether it is possible to use skipTo() when
|
||||
* TODO: Investigate whether it is possible to use skipTo() when
|
||||
* the minimum number of matchers is bigger than one, ie. try and use the
|
||||
* character of ConjunctionScorer for the minimum number of matchers.
|
||||
* Also delay calling score() on the sub scorers until the minimum number of
|
||||
|
@ -190,7 +197,7 @@ class DisjunctionSumScorer extends Scorer {
|
|||
currentScore = scorerDocQueue.topScore();
|
||||
nrMatchers = 1;
|
||||
do { // Until all subscorers are after currentDoc
|
||||
if (! scorerDocQueue.topNextAndAdjustElsePop()) {
|
||||
if (!scorerDocQueue.topNextAndAdjustElsePop()) {
|
||||
if (scorerDocQueue.size() == 0) {
|
||||
break; // nothing more to advance, check for last match.
|
||||
}
|
||||
|
@ -215,8 +222,13 @@ class DisjunctionSumScorer extends Scorer {
|
|||
*/
|
||||
public float score() throws IOException { return currentScore; }
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return currentDoc; }
|
||||
|
||||
public int docID() {
|
||||
return currentDoc;
|
||||
}
|
||||
|
||||
/** Returns the number of subscorers matching the current document.
|
||||
* Initially invalid, until {@link #next()} is called the first time.
|
||||
*/
|
||||
|
@ -224,31 +236,52 @@ class DisjunctionSumScorer extends Scorer {
|
|||
return nrMatchers;
|
||||
}
|
||||
|
||||
/** Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target.
|
||||
* <br>When this method is used the {@link #explain(int)} method should not be used.
|
||||
* <br>The implementation uses the skipTo() method on the subscorers.
|
||||
* @param target The target document number.
|
||||
/**
|
||||
* Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target. <br>
|
||||
* When this method is used the {@link #explain(int)} method should not be
|
||||
* used. <br>
|
||||
* The implementation uses the skipTo() method on the subscorers.
|
||||
*
|
||||
* @param target
|
||||
* The target document number.
|
||||
* @return true iff there is such a match.
|
||||
* @deprecated use {@link #advance(int)} instead.
|
||||
*/
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target. <br>
|
||||
* When this method is used the {@link #explain(int)} method should not be
|
||||
* used. <br>
|
||||
* The implementation uses the skipTo() method on the subscorers.
|
||||
*
|
||||
* @param target
|
||||
* The target document number.
|
||||
* @return the document whose number is greater than or equal to the given
|
||||
* target, or -1 if none exist.
|
||||
*/
|
||||
public int advance(int target) throws IOException {
|
||||
if (scorerDocQueue.size() < minimumNrMatchers) {
|
||||
return false;
|
||||
return currentDoc = NO_MORE_DOCS;
|
||||
}
|
||||
if (target <= currentDoc) {
|
||||
return true;
|
||||
return currentDoc;
|
||||
}
|
||||
do {
|
||||
if (scorerDocQueue.topDoc() >= target) {
|
||||
return advanceAfterCurrent();
|
||||
} else if (! scorerDocQueue.topSkipToAndAdjustElsePop(target)) {
|
||||
return advanceAfterCurrent() ? currentDoc : (currentDoc = NO_MORE_DOCS);
|
||||
} else if (!scorerDocQueue.topSkipToAndAdjustElsePop(target)) {
|
||||
if (scorerDocQueue.size() < minimumNrMatchers) {
|
||||
return false;
|
||||
return currentDoc = NO_MORE_DOCS;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
|
||||
/** @return An explanation for the score of a given document. */
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
Explanation res = new Explanation();
|
||||
|
|
|
@ -20,30 +20,130 @@ package org.apache.lucene.search;
|
|||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This abstract class defines methods to iterate over a set of
|
||||
* non-decreasing doc ids.
|
||||
* This abstract class defines methods to iterate over a set of non-decreasing
|
||||
* doc ids. Note that this class assumes it iterates on doc Ids, and therefore
|
||||
* {@link #NO_MORE_DOCS} is set to {@value #NO_MORE_DOCS} in order to be used as
|
||||
* a sentinel object. Implementations of this class are expected to consider
|
||||
* {@link Integer#MAX_VALUE} as an invalid value.
|
||||
*/
|
||||
public abstract class DocIdSetIterator {
|
||||
/** Returns the current document number. <p> This is invalid until {@link
|
||||
#next()} is called for the first time.*/
|
||||
public abstract int doc();
|
||||
|
||||
/** Moves to the next docId in the set. Returns true, iff
|
||||
* there is such a docId. */
|
||||
public abstract boolean next() throws IOException;
|
||||
|
||||
/** Skips entries to the first beyond the current whose document number is
|
||||
* greater than or equal to <i>target</i>. <p>Returns true iff there is such
|
||||
* an entry. <p>Behaves as if written: <pre>
|
||||
* boolean skipTo(int target) {
|
||||
* do {
|
||||
* if (!next())
|
||||
* return false;
|
||||
* } while (target > doc());
|
||||
* return true;
|
||||
* }
|
||||
* </pre>
|
||||
* Some implementations are considerably more efficient than that.
|
||||
*/
|
||||
public abstract boolean skipTo(int target) throws IOException;
|
||||
|
||||
// TODO (3.0): review the javadocs and remove any references to '3.0'.
|
||||
private int doc = -1;
|
||||
|
||||
/**
|
||||
* When returned by {@link #nextDoc()}, {@link #advance(int)} and
|
||||
* {@link #doc()} it means there are no more docs in the iterator.
|
||||
*/
|
||||
public static final int NO_MORE_DOCS = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Unsupported anymore. Call {@link #docID()} instead. This method throws
|
||||
* {@link UnsupportedOperationException} if called.
|
||||
*
|
||||
* @deprecated use {@link #docID()} instead.
|
||||
*/
|
||||
public int doc() {
|
||||
throw new UnsupportedOperationException("Call docID() instead.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the following:
|
||||
* <ul>
|
||||
* <li>-1 or {@link #NO_MORE_DOCS} if {@link #nextDoc()} or
|
||||
* {@link #advance(int)} were not called yet.
|
||||
* <li>{@link #NO_MORE_DOCS} if the iterator has exhausted.
|
||||
* <li>Otherwise it should return the doc ID it is currently on.
|
||||
* </ul>
|
||||
* <p>
|
||||
* <b>NOTE:</b> in 3.0, this method will become abstract.
|
||||
*
|
||||
* @since 2.9
|
||||
*/
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported anymore. Call {@link #nextDoc()} instead. This method throws
|
||||
* {@link UnsupportedOperationException} if called.
|
||||
*
|
||||
* @deprecated use {@link #nextDoc()} instead. This will be removed in 3.0
|
||||
*/
|
||||
public boolean next() throws IOException {
|
||||
throw new UnsupportedOperationException("Call nextDoc() instead.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported anymore. Call {@link #advance(int)} instead. This method throws
|
||||
* {@link UnsupportedOperationException} if called.
|
||||
*
|
||||
* @deprecated use {@link #advance(int)} instead. This will be removed in 3.0
|
||||
*/
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
throw new UnsupportedOperationException("Call advance() instead.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances to the next document in the set and returns the doc it is
|
||||
* currently on, or {@link #NO_MORE_DOCS} if there are no more docs in the
|
||||
* set.<br>
|
||||
*
|
||||
* <b>NOTE:</b> in 3.0 this method will become abstract, following the removal
|
||||
* of {@link #next()}. For backward compatibility it is implemented as:
|
||||
*
|
||||
* <pre>
|
||||
* public int nextDoc() throws IOException {
|
||||
* return next() ? doc() : NO_MORE_DOCS;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <b>NOTE:</b> after the iterator has exhausted you should not call this
|
||||
* method, as it may result in unpredicted behavior.
|
||||
*
|
||||
* @since 2.9
|
||||
*/
|
||||
public int nextDoc() throws IOException {
|
||||
return doc = next() ? doc() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances to the first beyond the current whose document number is greater
|
||||
* than or equal to <i>target</i>. Returns the current document number or
|
||||
* {@link #NO_MORE_DOCS} if there are no more docs in the set.
|
||||
* <p>
|
||||
* Behaves as if written:
|
||||
*
|
||||
* <pre>
|
||||
* int advance(int target) {
|
||||
* int doc;
|
||||
* while ((doc = nextDoc()) < target) {
|
||||
* }
|
||||
* return doc;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Some implementations are considerably more efficient than that.
|
||||
* <p>
|
||||
* <b>NOTE:</b> certain implemenations may return a different value (each
|
||||
* time) if called several times in a row with the same target.
|
||||
* <p>
|
||||
* <b>NOTE:</b> this method may be called with {@value #NO_MORE_DOCS} for
|
||||
* efficiency by some Scorers. If your implementation cannot efficiently
|
||||
* determine that it should exhaust, it is recommended that you check for that
|
||||
* value in each call to this method.
|
||||
* <p>
|
||||
* <b>NOTE:</b> after the iterator has exhausted you should not call this
|
||||
* method, as it may result in unpredicted behavior.
|
||||
* <p>
|
||||
* <b>NOTE:</b> in 3.0 this method will become abstract, following the removal
|
||||
* of {@link #skipTo(int)}.
|
||||
*
|
||||
* @since 2.9
|
||||
*/
|
||||
public int advance(int target) throws IOException {
|
||||
while (nextDoc() < target) {}
|
||||
return doc;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -158,37 +158,51 @@ public class FieldCacheRangeFilter extends Filter {
|
|||
|
||||
protected class RangeMultiFilterIterator extends DocIdSetIterator {
|
||||
private int doc = -1;
|
||||
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() {
|
||||
try {
|
||||
do {
|
||||
doc++;
|
||||
} while (fcsi.order[doc] > inclusiveUpperPoint
|
||||
|| fcsi.order[doc] < inclusiveLowerPoint);
|
||||
return true;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
doc = Integer.MAX_VALUE;
|
||||
return false;
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) {
|
||||
try {
|
||||
doc = target;
|
||||
while (fcsi.order[doc] > inclusiveUpperPoint
|
||||
|| fcsi.order[doc] < inclusiveLowerPoint) {
|
||||
doc++;
|
||||
}
|
||||
return true;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
doc = Integer.MAX_VALUE;
|
||||
return false;
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,11 @@ package org.apache.lucene.search;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.TermDocs; // for javadoc
|
||||
import org.apache.lucene.util.OpenBitSet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.util.OpenBitSet;
|
||||
|
||||
/**
|
||||
* A {@link Filter} that only accepts documents whose single
|
||||
* term value in the specified field is contained in the
|
||||
|
@ -133,33 +132,44 @@ public class FieldCacheTermsFilter extends Filter {
|
|||
protected class FieldCacheTermsFilterDocIdSetIterator extends DocIdSetIterator {
|
||||
private int doc = -1;
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
public boolean next() {
|
||||
try {
|
||||
do {
|
||||
doc++;
|
||||
} while (!openBitSet.fastGet(fcsi.order[doc]));
|
||||
return true;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
doc = Integer.MAX_VALUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() {
|
||||
try {
|
||||
while (!openBitSet.fastGet(fcsi.order[++doc])) {}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) {
|
||||
try {
|
||||
doc = target;
|
||||
while (!openBitSet.fastGet(fcsi.order[doc])) {
|
||||
doc++;
|
||||
}
|
||||
return true;
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
doc = Integer.MAX_VALUE;
|
||||
return false;
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,9 @@ import java.io.IOException;
|
|||
* mechanism on an underlying DocIdSetIterator. See {@link
|
||||
* FilteredDocIdSet}.
|
||||
*/
|
||||
|
||||
public abstract class FilteredDocIdSetIterator extends DocIdSetIterator {
|
||||
protected DocIdSetIterator _innerIter;
|
||||
private int _currentDoc;
|
||||
private int doc;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -39,7 +38,7 @@ public abstract class FilteredDocIdSetIterator extends DocIdSetIterator {
|
|||
throw new IllegalArgumentException("null iterator");
|
||||
}
|
||||
_innerIter = innerIter;
|
||||
_currentDoc = -1;
|
||||
doc = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,42 +49,49 @@ public abstract class FilteredDocIdSetIterator extends DocIdSetIterator {
|
|||
*/
|
||||
abstract protected boolean match(int doc);
|
||||
|
||||
// @Override
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public final int doc() {
|
||||
return _currentDoc;
|
||||
return doc;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public final boolean next() throws IOException{
|
||||
while (_innerIter.next()) {
|
||||
int doc = _innerIter.doc();
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
while ((doc = _innerIter.nextDoc()) != NO_MORE_DOCS) {
|
||||
if (match(doc)) {
|
||||
_currentDoc = doc;
|
||||
return true;
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return doc;
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public final boolean skipTo(int n) throws IOException{
|
||||
boolean flag = _innerIter.skipTo(n);
|
||||
if (flag) {
|
||||
int doc = _innerIter.doc();
|
||||
return advance(n) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
doc = _innerIter.advance(target);
|
||||
if (doc != NO_MORE_DOCS) {
|
||||
if (match(doc)) {
|
||||
_currentDoc = doc;
|
||||
return true;
|
||||
return doc;
|
||||
} else {
|
||||
while (_innerIter.next()) {
|
||||
int docid = _innerIter.doc();
|
||||
if (match(docid)) {
|
||||
_currentDoc = docid;
|
||||
return true;
|
||||
while ((doc = _innerIter.nextDoc()) != NO_MORE_DOCS) {
|
||||
if (match(doc)) {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
return doc;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ extends Query {
|
|||
}
|
||||
Filter f = FilteredQuery.this.filter;
|
||||
DocIdSetIterator docIdSetIterator = f.getDocIdSet(ir).iterator();
|
||||
if (docIdSetIterator.skipTo(i) && (docIdSetIterator.doc() == i)) {
|
||||
if (docIdSetIterator.advance(i) == i) {
|
||||
return inner;
|
||||
} else {
|
||||
Explanation result = new Explanation
|
||||
|
@ -99,35 +99,51 @@ extends Query {
|
|||
public Query getQuery() { return FilteredQuery.this; }
|
||||
|
||||
// return a filtering scorer
|
||||
public Scorer scorer (IndexReader indexReader) throws IOException {
|
||||
public Scorer scorer (IndexReader indexReader) throws IOException {
|
||||
final Scorer scorer = weight.scorer(indexReader);
|
||||
final DocIdSetIterator docIdSetIterator = filter.getDocIdSet(indexReader).iterator();
|
||||
|
||||
return new Scorer(similarity) {
|
||||
|
||||
private boolean advanceToCommon() throws IOException {
|
||||
while (scorer.doc() != docIdSetIterator.doc()) {
|
||||
if (scorer.doc() < docIdSetIterator.doc()) {
|
||||
if (!scorer.skipTo(docIdSetIterator.doc())) {
|
||||
return false;
|
||||
}
|
||||
} else if (!docIdSetIterator.skipTo(scorer.doc())) {
|
||||
return false;
|
||||
private int doc = -1;
|
||||
|
||||
private int advanceToCommon(int scorerDoc, int disiDoc) throws IOException {
|
||||
while (scorerDoc != disiDoc) {
|
||||
if (scorerDoc < disiDoc) {
|
||||
scorerDoc = scorer.advance(disiDoc);
|
||||
} else {
|
||||
disiDoc = docIdSetIterator.advance(scorerDoc);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return scorerDoc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return docIdSetIterator.next() && scorer.next() && advanceToCommon();
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
int scorerDoc, disiDoc;
|
||||
return doc = (disiDoc = docIdSetIterator.nextDoc()) != NO_MORE_DOCS
|
||||
&& (scorerDoc = scorer.nextDoc()) != NO_MORE_DOCS
|
||||
&& advanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS ? scorer.docID() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return scorer.doc(); }
|
||||
|
||||
public int docID() { return doc; }
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int i) throws IOException {
|
||||
return docIdSetIterator.skipTo(i)
|
||||
&& scorer.skipTo(docIdSetIterator.doc())
|
||||
&& advanceToCommon();
|
||||
return advance(i) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
int disiDoc, scorerDoc;
|
||||
return doc = (disiDoc = docIdSetIterator.advance(target)) != NO_MORE_DOCS
|
||||
&& (scorerDoc = scorer.advance(disiDoc)) != NO_MORE_DOCS
|
||||
&& advanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS ? scorer.docID() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public float score() throws IOException { return getBoost() * scorer.score(); }
|
||||
|
@ -136,7 +152,7 @@ extends Query {
|
|||
public Explanation explain (int i) throws IOException {
|
||||
Explanation exp = scorer.explain(i);
|
||||
|
||||
if (docIdSetIterator.skipTo(i) && (docIdSetIterator.doc() == i)) {
|
||||
if (docIdSetIterator.advance(i) == i) {
|
||||
exp.setDescription ("allowed by filter: "+exp.getDescription());
|
||||
exp.setValue(getBoost() * exp.getValue());
|
||||
} else {
|
||||
|
|
|
@ -258,28 +258,34 @@ public class IndexSearcher extends Searcher {
|
|||
if (scorer == null)
|
||||
return;
|
||||
|
||||
int docID = scorer.docID();
|
||||
assert docID == -1 || docID == DocIdSetIterator.NO_MORE_DOCS;
|
||||
|
||||
if (filter == null) {
|
||||
scorer.score(collector);
|
||||
return;
|
||||
}
|
||||
|
||||
DocIdSetIterator filterDocIdIterator = filter.getDocIdSet(reader).iterator(); // CHECKME: use ConjunctionScorer here?
|
||||
// CHECKME: use ConjunctionScorer here?
|
||||
DocIdSetIterator filterIter = filter.getDocIdSet(reader).iterator();
|
||||
|
||||
int filterDoc = filterIter.nextDoc();
|
||||
int scorerDoc = scorer.advance(filterDoc);
|
||||
|
||||
boolean more = filterDocIdIterator.next() && scorer.skipTo(filterDocIdIterator.doc());
|
||||
|
||||
collector.setScorer(scorer);
|
||||
while (more) {
|
||||
int filterDocId = filterDocIdIterator.doc();
|
||||
if (filterDocId > scorer.doc() && !scorer.skipTo(filterDocId)) {
|
||||
more = false;
|
||||
} else {
|
||||
int scorerDocId = scorer.doc();
|
||||
if (scorerDocId == filterDocId) { // permitted by filter
|
||||
collector.collect(scorerDocId);
|
||||
more = filterDocIdIterator.next();
|
||||
} else {
|
||||
more = filterDocIdIterator.skipTo(scorerDocId);
|
||||
while (true) {
|
||||
if (scorerDoc == filterDoc) {
|
||||
// Check if scorer has exhausted, only before collecting.
|
||||
if (scorerDoc == DocIdSetIterator.NO_MORE_DOCS) {
|
||||
break;
|
||||
}
|
||||
collector.collect(scorerDoc);
|
||||
filterDoc = filterIter.nextDoc();
|
||||
scorerDoc = scorer.advance(filterDoc);
|
||||
} else if (scorerDoc > filterDoc) {
|
||||
filterDoc = filterIter.advance(scorerDoc);
|
||||
} else {
|
||||
scorerDoc = scorer.advance(filterDoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,10 @@ public class MatchAllDocsQuery extends Query {
|
|||
final TermDocs termDocs;
|
||||
final float score;
|
||||
final byte[] norms;
|
||||
|
||||
MatchAllScorer(IndexReader reader, Similarity similarity, Weight w, byte[] norms) throws IOException
|
||||
{
|
||||
private int doc = -1;
|
||||
|
||||
MatchAllScorer(IndexReader reader, Similarity similarity, Weight w,
|
||||
byte[] norms) throws IOException {
|
||||
super(similarity);
|
||||
this.termDocs = reader.termDocs(null);
|
||||
score = w.getValue();
|
||||
|
@ -60,26 +61,36 @@ public class MatchAllDocsQuery extends Query {
|
|||
return null; // not called... see MatchAllDocsWeight.explain()
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return termDocs.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return termDocs.next();
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return doc = termDocs.next() ? termDocs.doc() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public float score() {
|
||||
if (norms == null) {
|
||||
return score;
|
||||
} else {
|
||||
return score * Similarity.decodeNorm(norms[doc()]); // normalize for field
|
||||
}
|
||||
return norms == null ? score : score * Similarity.decodeNorm(norms[docID()]);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return termDocs.skipTo(target);
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return doc = termDocs.skipTo(target) ? termDocs.doc() : NO_MORE_DOCS;
|
||||
}
|
||||
}
|
||||
|
||||
private class MatchAllDocsWeight implements Weight {
|
||||
|
|
|
@ -23,13 +23,22 @@ import java.io.IOException;
|
|||
class NonMatchingScorer extends Scorer {
|
||||
public NonMatchingScorer() { super(null); } // no similarity used
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { throw new UnsupportedOperationException(); }
|
||||
|
||||
public int docID() { return NO_MORE_DOCS; }
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException { return false; }
|
||||
|
||||
public int nextDoc() throws IOException { return NO_MORE_DOCS; }
|
||||
|
||||
public float score() { throw new UnsupportedOperationException(); }
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) { return false; }
|
||||
|
||||
public int advance(int target) { return NO_MORE_DOCS; }
|
||||
|
||||
public Explanation explain(int doc) {
|
||||
Explanation e = new Explanation();
|
||||
|
|
|
@ -43,9 +43,8 @@ abstract class PhraseScorer extends Scorer {
|
|||
|
||||
private float freq; //prhase frequency in current doc as computed by phraseFreq().
|
||||
|
||||
|
||||
PhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, Similarity similarity,
|
||||
byte[] norms) {
|
||||
PhraseScorer(Weight weight, TermPositions[] tps, int[] offsets,
|
||||
Similarity similarity, byte[] norms) {
|
||||
super(similarity);
|
||||
this.norms = norms;
|
||||
this.weight = weight;
|
||||
|
@ -60,25 +59,37 @@ abstract class PhraseScorer extends Scorer {
|
|||
PhrasePositions pp = new PhrasePositions(tps[i], offsets[i]);
|
||||
if (last != null) { // add next to end of list
|
||||
last.next = pp;
|
||||
} else
|
||||
} else {
|
||||
first = pp;
|
||||
}
|
||||
last = pp;
|
||||
}
|
||||
|
||||
pq = new PhraseQueue(tps.length); // construct empty pq
|
||||
|
||||
first.doc = -1;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return first.doc; }
|
||||
|
||||
public int docID() { return first.doc; }
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
if (firstTime) {
|
||||
init();
|
||||
firstTime = false;
|
||||
} else if (more) {
|
||||
more = last.next(); // trigger further scanning
|
||||
}
|
||||
return doNext();
|
||||
if (!doNext()) {
|
||||
first.doc = NO_MORE_DOCS;
|
||||
}
|
||||
return first.doc;
|
||||
}
|
||||
|
||||
// next without initial increment
|
||||
|
@ -107,16 +118,25 @@ abstract class PhraseScorer extends Scorer {
|
|||
return norms == null ? raw : raw * Similarity.decodeNorm(norms[first.doc]); // normalize
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
firstTime = false;
|
||||
for (PhrasePositions pp = first; more && pp != null; pp = pp.next) {
|
||||
more = pp.skipTo(target);
|
||||
}
|
||||
if (more)
|
||||
if (more) {
|
||||
sort(); // re-sort
|
||||
return doNext();
|
||||
}
|
||||
if (!doNext()) {
|
||||
first.doc = NO_MORE_DOCS;
|
||||
}
|
||||
return first.doc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For a document containing all the phrase query terms, compute the
|
||||
* frequency of the phrase in that document.
|
||||
|
@ -127,16 +147,19 @@ abstract class PhraseScorer extends Scorer {
|
|||
protected abstract float phraseFreq() throws IOException;
|
||||
|
||||
private void init() throws IOException {
|
||||
for (PhrasePositions pp = first; more && pp != null; pp = pp.next)
|
||||
for (PhrasePositions pp = first; more && pp != null; pp = pp.next) {
|
||||
more = pp.next();
|
||||
if(more)
|
||||
}
|
||||
if (more) {
|
||||
sort();
|
||||
}
|
||||
}
|
||||
|
||||
private void sort() {
|
||||
pq.clear();
|
||||
for (PhrasePositions pp = first; pp != null; pp = pp.next)
|
||||
pq.put(pp);
|
||||
for (PhrasePositions pp = first; pp != null; pp = pp.next) {
|
||||
pq.add(pp);
|
||||
}
|
||||
pqToList();
|
||||
}
|
||||
|
||||
|
@ -163,9 +186,8 @@ abstract class PhraseScorer extends Scorer {
|
|||
public Explanation explain(final int doc) throws IOException {
|
||||
Explanation tfExplanation = new Explanation();
|
||||
|
||||
while (next() && doc() < doc) {}
|
||||
|
||||
float phraseFreq = (doc() == doc) ? freq : 0.0f;
|
||||
int d = advance(doc);
|
||||
float phraseFreq = (d == doc) ? freq : 0.0f;
|
||||
tfExplanation.setValue(getSimilarity().tf(phraseFreq));
|
||||
tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")");
|
||||
|
||||
|
|
|
@ -29,76 +29,78 @@ import java.io.IOException;
|
|||
class ReqExclScorer extends Scorer {
|
||||
private Scorer reqScorer;
|
||||
private DocIdSetIterator exclDisi;
|
||||
private int doc = -1;
|
||||
|
||||
/** Construct a <code>ReqExclScorer</code>.
|
||||
* @param reqScorer The scorer that must match, except where
|
||||
* @param exclDisi indicates exclusion.
|
||||
*/
|
||||
public ReqExclScorer(
|
||||
Scorer reqScorer,
|
||||
DocIdSetIterator exclDisi) {
|
||||
public ReqExclScorer(Scorer reqScorer, DocIdSetIterator exclDisi) {
|
||||
super(null); // No similarity used.
|
||||
this.reqScorer = reqScorer;
|
||||
this.exclDisi = exclDisi;
|
||||
}
|
||||
|
||||
private boolean firstTime = true;
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
if (firstTime) {
|
||||
if (! exclDisi.next()) {
|
||||
exclDisi = null; // exhausted at start
|
||||
}
|
||||
firstTime = false;
|
||||
}
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
if (reqScorer == null) {
|
||||
return false;
|
||||
return doc;
|
||||
}
|
||||
if (! reqScorer.next()) {
|
||||
doc = reqScorer.nextDoc();
|
||||
if (doc == NO_MORE_DOCS) {
|
||||
reqScorer = null; // exhausted, nothing left
|
||||
return false;
|
||||
return doc;
|
||||
}
|
||||
if (exclDisi == null) {
|
||||
return true; // reqScorer.next() already returned true
|
||||
return doc;
|
||||
}
|
||||
return toNonExcluded();
|
||||
return doc = toNonExcluded();
|
||||
}
|
||||
|
||||
/** Advance to non excluded doc.
|
||||
* <br>On entry:
|
||||
* <ul>
|
||||
* <li>reqScorer != null,
|
||||
* <li>exclDisi != null,
|
||||
* <li>exclScorer != null,
|
||||
* <li>reqScorer was advanced once via next() or skipTo()
|
||||
* and reqScorer.doc() may still be excluded.
|
||||
* </ul>
|
||||
* Advances reqScorer a non excluded required doc, if any.
|
||||
* @return true iff there is a non excluded required doc.
|
||||
*/
|
||||
private boolean toNonExcluded() throws IOException {
|
||||
int exclDoc = exclDisi.doc();
|
||||
private int toNonExcluded() throws IOException {
|
||||
int exclDoc = exclDisi.docID();
|
||||
int reqDoc = reqScorer.docID(); // may be excluded
|
||||
do {
|
||||
int reqDoc = reqScorer.doc(); // may be excluded
|
||||
if (reqDoc < exclDoc) {
|
||||
return true; // reqScorer advanced to before exclScorer, ie. not excluded
|
||||
return reqDoc; // reqScorer advanced to before exclScorer, ie. not excluded
|
||||
} else if (reqDoc > exclDoc) {
|
||||
if (! exclDisi.skipTo(reqDoc)) {
|
||||
exclDoc = exclDisi.advance(reqDoc);
|
||||
if (exclDoc == NO_MORE_DOCS) {
|
||||
exclDisi = null; // exhausted, no more exclusions
|
||||
return true;
|
||||
return reqDoc;
|
||||
}
|
||||
exclDoc = exclDisi.doc();
|
||||
if (exclDoc > reqDoc) {
|
||||
return true; // not excluded
|
||||
return reqDoc; // not excluded
|
||||
}
|
||||
}
|
||||
} while (reqScorer.next());
|
||||
} while ((reqDoc = reqScorer.nextDoc()) != NO_MORE_DOCS);
|
||||
reqScorer = null; // exhausted, nothing left
|
||||
return false;
|
||||
return NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return reqScorer.doc(); // reqScorer may be null when next() or skipTo() already return false
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** Returns the score of the current document matching the query.
|
||||
* Initially invalid, until {@link #next()} is called the first time.
|
||||
|
@ -108,35 +110,28 @@ class ReqExclScorer extends Scorer {
|
|||
return reqScorer.score(); // reqScorer may be null when next() or skipTo() already return false
|
||||
}
|
||||
|
||||
/** Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target.
|
||||
* <br>When this method is used the {@link #explain(int)} method should not be used.
|
||||
* @param target The target document number.
|
||||
* @return true iff there is such a match.
|
||||
*/
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
if (! exclDisi.skipTo(target)) {
|
||||
exclDisi = null; // exhausted
|
||||
}
|
||||
}
|
||||
if (reqScorer == null) {
|
||||
return false;
|
||||
}
|
||||
if (exclDisi == null) {
|
||||
return reqScorer.skipTo(target);
|
||||
}
|
||||
if (! reqScorer.skipTo(target)) {
|
||||
reqScorer = null;
|
||||
return false;
|
||||
}
|
||||
return toNonExcluded();
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
if (reqScorer == null) {
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
if (exclDisi == null) {
|
||||
return doc = reqScorer.advance(target);
|
||||
}
|
||||
if (reqScorer.advance(target) == NO_MORE_DOCS) {
|
||||
reqScorer = null;
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc = toNonExcluded();
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
Explanation res = new Explanation();
|
||||
if (exclDisi.skipTo(doc) && (exclDisi.doc() == doc)) {
|
||||
if (exclDisi.advance(doc) == doc) {
|
||||
res.setDescription("excluded");
|
||||
} else {
|
||||
res.setDescription("not excluded");
|
||||
|
|
|
@ -43,44 +43,52 @@ class ReqOptSumScorer extends Scorer {
|
|||
this.optScorer = optScorer;
|
||||
}
|
||||
|
||||
private boolean firstTimeOptScorer = true;
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return reqScorer.next();
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return reqScorer.nextDoc();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return reqScorer.skipTo(target);
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return reqScorer.advance(target);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return reqScorer.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return reqScorer.docID();
|
||||
}
|
||||
|
||||
/** Returns the score of the current document matching the query.
|
||||
* Initially invalid, until {@link #next()} is called the first time.
|
||||
* @return The score of the required scorer, eventually increased by the score
|
||||
* of the optional scorer when it also matches the current document.
|
||||
*/
|
||||
public float score() throws IOException {
|
||||
int curDoc = reqScorer.doc();
|
||||
int curDoc = reqScorer.docID();
|
||||
float reqScore = reqScorer.score();
|
||||
if (firstTimeOptScorer) {
|
||||
firstTimeOptScorer = false;
|
||||
if (! optScorer.skipTo(curDoc)) {
|
||||
optScorer = null;
|
||||
return reqScore;
|
||||
}
|
||||
} else if (optScorer == null) {
|
||||
if (optScorer == null) {
|
||||
return reqScore;
|
||||
} else if ((optScorer.doc() < curDoc) && (! optScorer.skipTo(curDoc))) {
|
||||
}
|
||||
|
||||
int optScorerDoc = optScorer.docID();
|
||||
if (optScorerDoc < curDoc && (optScorerDoc = optScorer.advance(curDoc)) == NO_MORE_DOCS) {
|
||||
optScorer = null;
|
||||
return reqScore;
|
||||
}
|
||||
// assert (optScorer != null) && (optScorer.doc() >= curDoc);
|
||||
return (optScorer.doc() == curDoc)
|
||||
? reqScore + optScorer.score()
|
||||
: reqScore;
|
||||
|
||||
return optScorerDoc == curDoc ? reqScore + optScorer.score() : reqScore;
|
||||
}
|
||||
|
||||
/** Explain the score of a document.
|
||||
|
|
|
@ -42,8 +42,8 @@ public class ScoreCachingWrappingScorer extends Scorer {
|
|||
this.scorer = scorer;
|
||||
}
|
||||
|
||||
protected boolean score(Collector collector, int max) throws IOException {
|
||||
return scorer.score(collector, max);
|
||||
protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
return scorer.score(collector, max, firstDocID);
|
||||
}
|
||||
|
||||
public Similarity getSimilarity() {
|
||||
|
@ -55,7 +55,7 @@ public class ScoreCachingWrappingScorer extends Scorer {
|
|||
}
|
||||
|
||||
public float score() throws IOException {
|
||||
int doc = scorer.doc();
|
||||
int doc = scorer.docID();
|
||||
if (doc != curDoc) {
|
||||
curScore = scorer.score();
|
||||
curDoc = doc;
|
||||
|
@ -64,20 +64,35 @@ public class ScoreCachingWrappingScorer extends Scorer {
|
|||
return curScore;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return scorer.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return scorer.docID();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return scorer.next();
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return scorer.nextDoc();
|
||||
}
|
||||
|
||||
public void score(Collector collector) throws IOException {
|
||||
scorer.score(collector);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return scorer.skipTo(target);
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return scorer.advance(target);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,8 +71,9 @@ public abstract class Scorer extends DocIdSetIterator {
|
|||
*/
|
||||
public void score(Collector collector) throws IOException {
|
||||
collector.setScorer(this);
|
||||
while (next()) {
|
||||
collector.collect(doc());
|
||||
int doc;
|
||||
while ((doc = nextDoc()) != NO_MORE_DOCS) {
|
||||
collector.collect(doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,26 +87,33 @@ public abstract class Scorer extends DocIdSetIterator {
|
|||
* @deprecated use {@link #score(Collector, int)} instead.
|
||||
*/
|
||||
protected boolean score(HitCollector hc, int max) throws IOException {
|
||||
return score(new HitCollectorWrapper(hc), max);
|
||||
return score(new HitCollectorWrapper(hc), max, docID());
|
||||
}
|
||||
|
||||
/** Expert: Collects matching documents in a range. Hook for optimization.
|
||||
* Note that {@link #next()} must be called once before this method is called
|
||||
* for the first time.
|
||||
* @param collector The collector to which all matching documents are passed.
|
||||
* @param max Do not score documents past this.
|
||||
/**
|
||||
* Expert: Collects matching documents in a range. Hook for optimization.
|
||||
* Note, <code>firstDocID</code> is added to ensure that {@link #nextDoc()}
|
||||
* was called before this method.
|
||||
*
|
||||
* @param collector
|
||||
* The collector to which all matching documents are passed.
|
||||
* @param max
|
||||
* Do not score documents past this.
|
||||
* @param firstDocID
|
||||
* The first document ID (ensures {@link #nextDoc()} is called before
|
||||
* this method.
|
||||
* @return true if more matching documents may remain.
|
||||
*/
|
||||
protected boolean score(Collector collector, int max) throws IOException {
|
||||
protected boolean score(Collector collector, int max, int firstDocID) throws IOException {
|
||||
collector.setScorer(this);
|
||||
while (doc() < max) {
|
||||
collector.collect(doc());
|
||||
if (!next())
|
||||
return false;
|
||||
int doc = firstDocID;
|
||||
while (doc < max) {
|
||||
collector.collect(doc);
|
||||
doc = nextDoc();
|
||||
}
|
||||
return true;
|
||||
return doc == NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the score of the current document matching the query.
|
||||
* Initially invalid, until {@link #next()} or {@link #skipTo(int)}
|
||||
* is called the first time, or when called from within
|
||||
|
|
|
@ -31,7 +31,7 @@ final class TermScorer extends Scorer {
|
|||
private TermDocs termDocs;
|
||||
private byte[] norms;
|
||||
private float weightValue;
|
||||
private int doc;
|
||||
private int doc = -1;
|
||||
|
||||
private final int[] docs = new int[32]; // buffered doc numbers
|
||||
private final int[] freqs = new int[32]; // buffered term freqs
|
||||
|
@ -65,16 +65,16 @@ final class TermScorer extends Scorer {
|
|||
}
|
||||
|
||||
public void score(Collector c) throws IOException {
|
||||
next();
|
||||
score(c, Integer.MAX_VALUE);
|
||||
score(c, Integer.MAX_VALUE, nextDoc());
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #score(Collector, int)} instead. */
|
||||
protected boolean score(HitCollector c, int end) throws IOException {
|
||||
return score(new HitCollectorWrapper(c), end);
|
||||
return score(new HitCollectorWrapper(c), end, doc);
|
||||
}
|
||||
|
||||
protected boolean score(Collector c, int end) throws IOException {
|
||||
// firstDocID is ignored since nextDoc() sets 'doc'
|
||||
protected boolean score(Collector c, int end, int firstDocID) throws IOException {
|
||||
c.setScorer(this);
|
||||
while (doc < end) { // for docs in window
|
||||
c.collect(doc); // collect score
|
||||
|
@ -94,17 +94,31 @@ final class TermScorer extends Scorer {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Returns the current document number matching the query.
|
||||
* Initially invalid, until {@link #next()} is called the first time.
|
||||
*/
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return doc; }
|
||||
|
||||
public int docID() { return doc; }
|
||||
|
||||
/** Advances to the next document matching the query.
|
||||
* <br>The iterator over the matching documents is buffered using
|
||||
/**
|
||||
* Advances to the next document matching the query. <br>
|
||||
* The iterator over the matching documents is buffered using
|
||||
* {@link TermDocs#read(int[],int[])}.
|
||||
*
|
||||
* @return true iff there is another document matching the query.
|
||||
* @deprecated use {@link #nextDoc()} instead.
|
||||
*/
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances to the next document matching the query. <br>
|
||||
* The iterator over the matching documents is buffered using
|
||||
* {@link TermDocs#read(int[],int[])}.
|
||||
*
|
||||
* @return the document matching the query or -1 if there are no more documents.
|
||||
*/
|
||||
public int nextDoc() throws IOException {
|
||||
pointer++;
|
||||
if (pointer >= pointerMax) {
|
||||
pointerMax = termDocs.read(docs, freqs); // refill buffer
|
||||
|
@ -112,15 +126,15 @@ final class TermScorer extends Scorer {
|
|||
pointer = 0;
|
||||
} else {
|
||||
termDocs.close(); // close stream
|
||||
doc = Integer.MAX_VALUE; // set to sentinel value
|
||||
return false;
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
}
|
||||
doc = docs[pointer];
|
||||
return true;
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
public float score() {
|
||||
assert doc != -1;
|
||||
int f = freqs[pointer];
|
||||
float raw = // compute tf(f)*weight
|
||||
f < SCORE_CACHE_SIZE // check cache
|
||||
|
@ -130,18 +144,34 @@ final class TermScorer extends Scorer {
|
|||
return norms == null ? raw : raw * SIM_NORM_DECODER[norms[doc] & 0xFF]; // normalize for field
|
||||
}
|
||||
|
||||
/** Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target.
|
||||
* <br>The implementation uses {@link TermDocs#skipTo(int)}.
|
||||
* @param target The target document number.
|
||||
/**
|
||||
* Skips to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target. <br>
|
||||
* The implementation uses {@link TermDocs#skipTo(int)}.
|
||||
*
|
||||
* @param target
|
||||
* The target document number.
|
||||
* @return true iff there is such a match.
|
||||
* @deprecated use {@link #advance(int)} instead.
|
||||
*/
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances to the first match beyond the current whose document number is
|
||||
* greater than or equal to a given target. <br>
|
||||
* The implementation uses {@link TermDocs#skipTo(int)}.
|
||||
*
|
||||
* @param target
|
||||
* The target document number.
|
||||
* @return the matching document or -1 if none exist.
|
||||
*/
|
||||
public int advance(int target) throws IOException {
|
||||
// first scan in cache
|
||||
for (pointer++; pointer < pointerMax; pointer++) {
|
||||
if (docs[pointer] >= target) {
|
||||
doc = docs[pointer];
|
||||
return true;
|
||||
return doc = docs[pointer];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,11 +183,11 @@ final class TermScorer extends Scorer {
|
|||
docs[pointer] = doc = termDocs.doc();
|
||||
freqs[pointer] = termDocs.freq();
|
||||
} else {
|
||||
doc = Integer.MAX_VALUE;
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return result;
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
/** Returns an explanation of the score for a document.
|
||||
* <br>When this method is used, the {@link #next()} method
|
||||
* and the {@link #score(HitCollector)} method should not be used.
|
||||
|
|
|
@ -367,41 +367,53 @@ public class CustomScoreQuery extends Query {
|
|||
this.vScores = new float[valSrcScorers.length];
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
boolean hasNext = subQueryScorer.next();
|
||||
if (hasNext) {
|
||||
for(int i = 0; i < valSrcScorers.length; i++) {
|
||||
valSrcScorers[i].skipTo(subQueryScorer.doc());
|
||||
}
|
||||
}
|
||||
return hasNext;
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() */
|
||||
public int nextDoc() throws IOException {
|
||||
int doc = subQueryScorer.nextDoc();
|
||||
if (doc != NO_MORE_DOCS) {
|
||||
for (int i = 0; i < valSrcScorers.length; i++) {
|
||||
valSrcScorers[i].advance(doc);
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return subQueryScorer.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return subQueryScorer.docID();
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
|
||||
public float score() throws IOException {
|
||||
for(int i = 0; i < valSrcScorers.length; i++) {
|
||||
for (int i = 0; i < valSrcScorers.length; i++) {
|
||||
vScores[i] = valSrcScorers[i].score();
|
||||
}
|
||||
return qWeight * customScore(subQueryScorer.doc(), subQueryScorer.score(), vScores);
|
||||
return qWeight * customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
boolean hasNext = subQueryScorer.skipTo(target);
|
||||
if (hasNext) {
|
||||
for (int i = 0; i < valSrcScorers.length; i++) {
|
||||
valSrcScorers[i].skipTo(subQueryScorer.doc());
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
int doc = subQueryScorer.advance(target);
|
||||
if (doc != NO_MORE_DOCS) {
|
||||
for (int i = 0; i < valSrcScorers.length; i++) {
|
||||
valSrcScorers[i].advance(doc);
|
||||
}
|
||||
}
|
||||
return hasNext;
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
Explanation subQueryExpl = weight.subQueryWeight.explain(reader,doc);
|
||||
|
|
|
@ -115,6 +115,7 @@ public class ValueSourceQuery extends Query {
|
|||
private final float qWeight;
|
||||
private final DocValues vals;
|
||||
private final TermDocs termDocs;
|
||||
private int doc = -1;
|
||||
|
||||
// constructor
|
||||
private ValueSourceScorer(Similarity similarity, IndexReader reader, ValueSourceWeight w) throws IOException {
|
||||
|
@ -126,26 +127,37 @@ public class ValueSourceQuery extends Query {
|
|||
termDocs = reader.termDocs(null);
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return termDocs.next();
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc()
|
||||
*/
|
||||
public int nextDoc() throws IOException {
|
||||
return doc = termDocs.next() ? termDocs.doc() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return termDocs.doc();
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
|
||||
public float score() throws IOException {
|
||||
return qWeight * vals.floatVal(termDocs.doc());
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return termDocs.skipTo(target);
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return doc = termDocs.skipTo(target) ? termDocs.doc() : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
|
|
|
@ -33,6 +33,7 @@ public class SpanScorer extends Scorer {
|
|||
protected byte[] norms;
|
||||
protected float value;
|
||||
|
||||
/** @deprecated not needed anymore */
|
||||
protected boolean firstTime = true;
|
||||
protected boolean more = true;
|
||||
|
||||
|
@ -46,33 +47,46 @@ public class SpanScorer extends Scorer {
|
|||
this.norms = norms;
|
||||
this.weight = weight;
|
||||
this.value = weight.getValue();
|
||||
doc = -1;
|
||||
if (this.spans.next()) {
|
||||
doc = -1;
|
||||
} else {
|
||||
doc = NO_MORE_DOCS;
|
||||
more = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
if (firstTime) {
|
||||
more = spans.next();
|
||||
firstTime = false;
|
||||
}
|
||||
return setFreqCurrentDoc();
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (firstTime) {
|
||||
more = spans.skipTo(target);
|
||||
firstTime = false;
|
||||
public int nextDoc() throws IOException {
|
||||
if (!setFreqCurrentDoc()) {
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
if (! more) {
|
||||
return false;
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
if (!more) {
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
if (spans.doc() < target) { // setFreqCurrentDoc() leaves spans.doc() ahead
|
||||
more = spans.skipTo(target);
|
||||
}
|
||||
return setFreqCurrentDoc();
|
||||
if (!setFreqCurrentDoc()) {
|
||||
doc = NO_MORE_DOCS;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
|
||||
protected boolean setFreqCurrentDoc() throws IOException {
|
||||
if (! more) {
|
||||
if (!more) {
|
||||
return false;
|
||||
}
|
||||
doc = spans.doc();
|
||||
|
@ -85,7 +99,10 @@ public class SpanScorer extends Scorer {
|
|||
return true;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return doc; }
|
||||
|
||||
public int docID() { return doc; }
|
||||
|
||||
public float score() throws IOException {
|
||||
float raw = getSimilarity().tf(freq) * value; // raw score
|
||||
|
@ -95,9 +112,9 @@ public class SpanScorer extends Scorer {
|
|||
public Explanation explain(final int doc) throws IOException {
|
||||
Explanation tfExplanation = new Explanation();
|
||||
|
||||
skipTo(doc);
|
||||
int expDoc = advance(doc);
|
||||
|
||||
float phraseFreq = (doc() == doc) ? freq : 0.0f;
|
||||
float phraseFreq = (expDoc == doc) ? freq : 0.0f;
|
||||
tfExplanation.setValue(getSimilarity().tf(phraseFreq));
|
||||
tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")");
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.lucene.util;
|
|||
*/
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.apache.lucene.search.DocIdSet;
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
|
||||
|
@ -50,28 +51,40 @@ public class DocIdBitSet extends DocIdSet {
|
|||
this.docId = -1;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
assert docId != -1;
|
||||
return docId;
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return docId;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() {
|
||||
// (docId + 1) on next line requires -1 initial value for docNr:
|
||||
return checkNextDocId(bitSet.nextSetBit(docId + 1));
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() {
|
||||
// (docId + 1) on next line requires -1 initial value for docNr:
|
||||
int d = bitSet.nextSetBit(docId + 1);
|
||||
// -1 returned by BitSet.nextSetBit() when exhausted
|
||||
docId = d == -1 ? NO_MORE_DOCS : d;
|
||||
return docId;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int skipDocNr) {
|
||||
return checkNextDocId( bitSet.nextSetBit(skipDocNr));
|
||||
return advance(skipDocNr) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
private boolean checkNextDocId(int d) {
|
||||
if (d == -1) { // -1 returned by BitSet.nextSetBit() when exhausted
|
||||
docId = Integer.MAX_VALUE;
|
||||
return false;
|
||||
} else {
|
||||
docId = d;
|
||||
return true;
|
||||
}
|
||||
public int advance(int target) {
|
||||
int d = bitSet.nextSetBit(target);
|
||||
// -1 returned by BitSet.nextSetBit() when exhausted
|
||||
docId = d == -1 ? NO_MORE_DOCS : d;
|
||||
return docId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,10 @@ public class OpenBitSetDISI extends OpenBitSet {
|
|||
* constructor.
|
||||
*/
|
||||
public void inPlaceOr(DocIdSetIterator disi) throws IOException {
|
||||
while (disi.next() && (disi.doc() < size())) {
|
||||
fastSet(disi.doc());
|
||||
int doc;
|
||||
long size = size();
|
||||
while ((doc = disi.nextDoc()) < size) {
|
||||
fastSet(doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,8 +62,8 @@ public class OpenBitSetDISI extends OpenBitSet {
|
|||
*/
|
||||
public void inPlaceAnd(DocIdSetIterator disi) throws IOException {
|
||||
int bitSetDoc = nextSetBit(0);
|
||||
while ((bitSetDoc != -1) && disi.skipTo(bitSetDoc)) {
|
||||
int disiDoc = disi.doc();
|
||||
int disiDoc;
|
||||
while (bitSetDoc != -1 && (disiDoc = disi.advance(bitSetDoc)) != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
clear(bitSetDoc, disiDoc);
|
||||
bitSetDoc = nextSetBit(disiDoc + 1);
|
||||
}
|
||||
|
@ -77,8 +79,10 @@ public class OpenBitSetDISI extends OpenBitSet {
|
|||
* constructor.
|
||||
*/
|
||||
public void inPlaceNot(DocIdSetIterator disi) throws IOException {
|
||||
while (disi.next() && (disi.doc() < size())) {
|
||||
fastClear(disi.doc());
|
||||
int doc;
|
||||
long size = size();
|
||||
while ((doc = disi.nextDoc()) < size) {
|
||||
fastClear(doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,8 +93,10 @@ public class OpenBitSetDISI extends OpenBitSet {
|
|||
* constructor.
|
||||
*/
|
||||
public void inPlaceXor(DocIdSetIterator disi) throws IOException {
|
||||
while (disi.next() && (disi.doc() < size())) {
|
||||
fastFlip(disi.doc());
|
||||
int doc;
|
||||
long size = size();
|
||||
while ((doc = disi.nextDoc()) < size) {
|
||||
fastFlip(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package org.apache.lucene.util;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
|
||||
/** An iterator to iterate over set bits in an OpenBitSet.
|
||||
|
@ -35,7 +33,34 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
// should be faster than accessing an array for each index, and
|
||||
// the total array size is kept smaller (256*sizeof(int))=1K
|
||||
protected final static int[] bitlist={
|
||||
0x0,0x1,0x2,0x21,0x3,0x31,0x32,0x321,0x4,0x41,0x42,0x421,0x43,0x431,0x432,0x4321,0x5,0x51,0x52,0x521,0x53,0x531,0x532,0x5321,0x54,0x541,0x542,0x5421,0x543,0x5431,0x5432,0x54321,0x6,0x61,0x62,0x621,0x63,0x631,0x632,0x6321,0x64,0x641,0x642,0x6421,0x643,0x6431,0x6432,0x64321,0x65,0x651,0x652,0x6521,0x653,0x6531,0x6532,0x65321,0x654,0x6541,0x6542,0x65421,0x6543,0x65431,0x65432,0x654321,0x7,0x71,0x72,0x721,0x73,0x731,0x732,0x7321,0x74,0x741,0x742,0x7421,0x743,0x7431,0x7432,0x74321,0x75,0x751,0x752,0x7521,0x753,0x7531,0x7532,0x75321,0x754,0x7541,0x7542,0x75421,0x7543,0x75431,0x75432,0x754321,0x76,0x761,0x762,0x7621,0x763,0x7631,0x7632,0x76321,0x764,0x7641,0x7642,0x76421,0x7643,0x76431,0x76432,0x764321,0x765,0x7651,0x7652,0x76521,0x7653,0x76531,0x76532,0x765321,0x7654,0x76541,0x76542,0x765421,0x76543,0x765431,0x765432,0x7654321,0x8,0x81,0x82,0x821,0x83,0x831,0x832,0x8321,0x84,0x841,0x842,0x8421,0x843,0x8431,0x8432,0x84321,0x85,0x851,0x852,0x8521,0x853,0x8531,0x8532,0x85321,0x854,0x8541,0x8542,0x85421,0x8543,0x85431,0x85432,0x854321,0x86,0x861,0x862,0x8621,0x863,0x8631,0x8632,0x86321,0x864,0x8641,0x8642,0x86421,0x8643,0x86431,0x86432,0x864321,0x865,0x8651,0x8652,0x86521,0x8653,0x86531,0x86532,0x865321,0x8654,0x86541,0x86542,0x865421,0x86543,0x865431,0x865432,0x8654321,0x87,0x871,0x872,0x8721,0x873,0x8731,0x8732,0x87321,0x874,0x8741,0x8742,0x87421,0x8743,0x87431,0x87432,0x874321,0x875,0x8751,0x8752,0x87521,0x8753,0x87531,0x87532,0x875321,0x8754,0x87541,0x87542,0x875421,0x87543,0x875431,0x875432,0x8754321,0x876,0x8761,0x8762,0x87621,0x8763,0x87631,0x87632,0x876321,0x8764,0x87641,0x87642,0x876421,0x87643,0x876431,0x876432,0x8764321,0x8765,0x87651,0x87652,0x876521,0x87653,0x876531,0x876532,0x8765321,0x87654,0x876541,0x876542,0x8765421,0x876543,0x8765431,0x8765432,0x87654321
|
||||
0x0, 0x1, 0x2, 0x21, 0x3, 0x31, 0x32, 0x321, 0x4, 0x41, 0x42, 0x421, 0x43,
|
||||
0x431, 0x432, 0x4321, 0x5, 0x51, 0x52, 0x521, 0x53, 0x531, 0x532, 0x5321,
|
||||
0x54, 0x541, 0x542, 0x5421, 0x543, 0x5431, 0x5432, 0x54321, 0x6, 0x61, 0x62,
|
||||
0x621, 0x63, 0x631, 0x632, 0x6321, 0x64, 0x641, 0x642, 0x6421, 0x643,
|
||||
0x6431, 0x6432, 0x64321, 0x65, 0x651, 0x652, 0x6521, 0x653, 0x6531, 0x6532,
|
||||
0x65321, 0x654, 0x6541, 0x6542, 0x65421, 0x6543, 0x65431, 0x65432, 0x654321,
|
||||
0x7, 0x71, 0x72, 0x721, 0x73, 0x731, 0x732, 0x7321, 0x74, 0x741, 0x742,
|
||||
0x7421, 0x743, 0x7431, 0x7432, 0x74321, 0x75, 0x751, 0x752, 0x7521, 0x753,
|
||||
0x7531, 0x7532, 0x75321, 0x754, 0x7541, 0x7542, 0x75421, 0x7543, 0x75431,
|
||||
0x75432, 0x754321, 0x76, 0x761, 0x762, 0x7621, 0x763, 0x7631, 0x7632,
|
||||
0x76321, 0x764, 0x7641, 0x7642, 0x76421, 0x7643, 0x76431, 0x76432, 0x764321,
|
||||
0x765, 0x7651, 0x7652, 0x76521, 0x7653, 0x76531, 0x76532, 0x765321, 0x7654,
|
||||
0x76541, 0x76542, 0x765421, 0x76543, 0x765431, 0x765432, 0x7654321, 0x8,
|
||||
0x81, 0x82, 0x821, 0x83, 0x831, 0x832, 0x8321, 0x84, 0x841, 0x842, 0x8421,
|
||||
0x843, 0x8431, 0x8432, 0x84321, 0x85, 0x851, 0x852, 0x8521, 0x853, 0x8531,
|
||||
0x8532, 0x85321, 0x854, 0x8541, 0x8542, 0x85421, 0x8543, 0x85431, 0x85432,
|
||||
0x854321, 0x86, 0x861, 0x862, 0x8621, 0x863, 0x8631, 0x8632, 0x86321, 0x864,
|
||||
0x8641, 0x8642, 0x86421, 0x8643, 0x86431, 0x86432, 0x864321, 0x865, 0x8651,
|
||||
0x8652, 0x86521, 0x8653, 0x86531, 0x86532, 0x865321, 0x8654, 0x86541,
|
||||
0x86542, 0x865421, 0x86543, 0x865431, 0x865432, 0x8654321, 0x87, 0x871,
|
||||
0x872, 0x8721, 0x873, 0x8731, 0x8732, 0x87321, 0x874, 0x8741, 0x8742,
|
||||
0x87421, 0x8743, 0x87431, 0x87432, 0x874321, 0x875, 0x8751, 0x8752, 0x87521,
|
||||
0x8753, 0x87531, 0x87532, 0x875321, 0x8754, 0x87541, 0x87542, 0x875421,
|
||||
0x87543, 0x875431, 0x875432, 0x8754321, 0x876, 0x8761, 0x8762, 0x87621,
|
||||
0x8763, 0x87631, 0x87632, 0x876321, 0x8764, 0x87641, 0x87642, 0x876421,
|
||||
0x87643, 0x876431, 0x876432, 0x8764321, 0x8765, 0x87651, 0x87652, 0x876521,
|
||||
0x87653, 0x876531, 0x876532, 0x8765321, 0x87654, 0x876541, 0x876542,
|
||||
0x8765421, 0x876543, 0x8765431, 0x8765432, 0x87654321
|
||||
};
|
||||
/***** the python code that generated bitlist
|
||||
def bits2int(val):
|
||||
|
@ -56,14 +81,13 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
// for efficiency, or have a common root interface? (or
|
||||
// maybe both? could ask for a SetBitsIterator, etc...
|
||||
|
||||
|
||||
private final long[] arr;
|
||||
private final int words;
|
||||
private int i=-1;
|
||||
private long word;
|
||||
private int wordShift;
|
||||
private int indexArray;
|
||||
private int curDocId;
|
||||
private int curDocId = -1;
|
||||
|
||||
public OpenBitSetIterator(OpenBitSet obs) {
|
||||
this(obs.getBits(), obs.getNumWords());
|
||||
|
@ -104,50 +128,24 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
}
|
||||
******/
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() {
|
||||
if (indexArray==0) {
|
||||
if (word!=0) {
|
||||
word >>>= 8;
|
||||
wordShift += 8;
|
||||
}
|
||||
|
||||
while (word==0) {
|
||||
if (++i >= words) {
|
||||
curDocId = -1;
|
||||
return false;
|
||||
}
|
||||
word = arr[i];
|
||||
wordShift =-1; // loop invariant code motion should move this
|
||||
}
|
||||
|
||||
// after the first time, should I go with a linear search, or
|
||||
// stick with the binary search in shift?
|
||||
shift();
|
||||
}
|
||||
|
||||
int bitIndex = (indexArray & 0x0f) + wordShift;
|
||||
indexArray >>>= 4;
|
||||
// should i<<6 be cached as a separate variable?
|
||||
// it would only save one cycle in the best circumstances.
|
||||
curDocId = (i<<6) + bitIndex;
|
||||
return true;
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** Moves iterator to the next doc and returns its id;
|
||||
returns -1 when this iterator is exhausted. */
|
||||
public int nextDoc() {
|
||||
if (indexArray==0) {
|
||||
if (word!=0) {
|
||||
if (indexArray == 0) {
|
||||
if (word != 0) {
|
||||
word >>>= 8;
|
||||
wordShift += 8;
|
||||
}
|
||||
|
||||
while (word==0) {
|
||||
while (word == 0) {
|
||||
if (++i >= words) {
|
||||
return curDocId = -1;
|
||||
return curDocId = NO_MORE_DOCS;
|
||||
}
|
||||
word = arr[i];
|
||||
wordShift =-1; // loop invariant code motion should move this
|
||||
wordShift = -1; // loop invariant code motion should move this
|
||||
}
|
||||
|
||||
// after the first time, should I go with a linear search, or
|
||||
|
@ -162,60 +160,30 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
return curDocId = (i<<6) + bitIndex;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) {
|
||||
indexArray=0;
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) {
|
||||
indexArray = 0;
|
||||
i = target >> 6;
|
||||
if (i>=words) {
|
||||
word =0; // setup so next() will also return -1
|
||||
curDocId = -1;
|
||||
return false;
|
||||
if (i >= words) {
|
||||
word = 0; // setup so next() will also return -1
|
||||
return curDocId = NO_MORE_DOCS;
|
||||
}
|
||||
wordShift = target & 0x3f;
|
||||
word = arr[i] >>> wordShift;
|
||||
if (word !=0) {
|
||||
if (word != 0) {
|
||||
wordShift--; // compensate for 1 based arrIndex
|
||||
} else {
|
||||
while (word ==0) {
|
||||
while (word == 0) {
|
||||
if (++i >= words) {
|
||||
curDocId = -1;
|
||||
return false;
|
||||
return curDocId = NO_MORE_DOCS;
|
||||
}
|
||||
word = arr[i];
|
||||
}
|
||||
wordShift =-1;
|
||||
}
|
||||
|
||||
shift();
|
||||
|
||||
int bitIndex = (indexArray & 0x0f) + wordShift;
|
||||
indexArray >>>= 4;
|
||||
// should i<<6 be cached as a separate variable?
|
||||
// it would only save one cycle in the best circumstances.
|
||||
curDocId = (i<<6) + bitIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Behaves like {@link #skipTo(int)} and returns the docId the iterator
|
||||
* skipped to; returns -1 if no valid document could be skipped to. */
|
||||
public int next(int fromIndex) {
|
||||
indexArray=0;
|
||||
i = fromIndex >> 6;
|
||||
if (i>=words) {
|
||||
word =0; // setup so next() will also return -1
|
||||
return curDocId = -1;
|
||||
}
|
||||
wordShift = fromIndex & 0x3f;
|
||||
word = arr[i] >>> wordShift;
|
||||
if (word !=0) {
|
||||
wordShift--; // compensate for 1 based arrIndex
|
||||
} else {
|
||||
while (word ==0) {
|
||||
if (++i >= words) {
|
||||
return curDocId = -1;
|
||||
}
|
||||
word = arr[i];
|
||||
}
|
||||
wordShift =-1;
|
||||
wordShift = -1;
|
||||
}
|
||||
|
||||
shift();
|
||||
|
@ -226,9 +194,14 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
// it would only save one cycle in the best circumstances.
|
||||
return curDocId = (i<<6) + bitIndex;
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return this.curDocId;
|
||||
return curDocId;
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
return curDocId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.lucene.util;
|
|||
/* Derived from org.apache.lucene.util.PriorityQueue of March 2005 */
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
|
||||
/** A ScorerDocQueue maintains a partial ordering of its Scorers such that the
|
||||
|
@ -35,14 +37,14 @@ public class ScorerDocQueue { // later: SpansQueue for spans with doc and term
|
|||
Scorer scorer;
|
||||
int doc;
|
||||
|
||||
HeapedScorerDoc(Scorer s) { this(s, s.doc()); }
|
||||
HeapedScorerDoc(Scorer s) { this(s, s.docID()); }
|
||||
|
||||
HeapedScorerDoc(Scorer scorer, int doc) {
|
||||
this.scorer = scorer;
|
||||
this.doc = doc;
|
||||
}
|
||||
|
||||
void adjust() { doc = scorer.doc(); }
|
||||
void adjust() { doc = scorer.docID(); }
|
||||
}
|
||||
|
||||
private HeapedScorerDoc topHSD; // same as heap[1], only for speed
|
||||
|
@ -79,7 +81,7 @@ public class ScorerDocQueue { // later: SpansQueue for spans with doc and term
|
|||
put(scorer);
|
||||
return true;
|
||||
} else {
|
||||
int docNr = scorer.doc();
|
||||
int docNr = scorer.docID();
|
||||
if ((size > 0) && (! (docNr < topHSD.doc))) { // heap[1] is top()
|
||||
heap[1] = new HeapedScorerDoc(scorer, docNr);
|
||||
downHeap();
|
||||
|
@ -113,16 +115,16 @@ public class ScorerDocQueue { // later: SpansQueue for spans with doc and term
|
|||
}
|
||||
|
||||
public final boolean topNextAndAdjustElsePop() throws IOException {
|
||||
return checkAdjustElsePop( topHSD.scorer.next());
|
||||
return checkAdjustElsePop(topHSD.scorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
public final boolean topSkipToAndAdjustElsePop(int target) throws IOException {
|
||||
return checkAdjustElsePop( topHSD.scorer.skipTo(target));
|
||||
return checkAdjustElsePop(topHSD.scorer.advance(target) != DocIdSetIterator.NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
private boolean checkAdjustElsePop(boolean cond) {
|
||||
if (cond) { // see also adjustTop
|
||||
topHSD.doc = topHSD.scorer.doc();
|
||||
topHSD.doc = topHSD.scorer.docID();
|
||||
} else { // see also popNoResult
|
||||
heap[1] = heap[size]; // move last to first
|
||||
heap[size] = null;
|
||||
|
|
|
@ -24,10 +24,15 @@ import org.apache.lucene.search.DocIdSet;
|
|||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
|
||||
/**
|
||||
* Store and iterate sorted integers in compressed form in RAM.
|
||||
* <br>The code for compressing the differences between ascending integers was
|
||||
* borrowed from {@link org.apache.lucene.store.IndexInput} and
|
||||
* {@link org.apache.lucene.store.IndexOutput}.
|
||||
* Stores and iterate on sorted integers in compressed form in RAM. <br>
|
||||
* The code for compressing the differences between ascending integers was
|
||||
* borrowed from {@link org.apache.lucene.store.IndexInput} and
|
||||
* {@link org.apache.lucene.store.IndexOutput}.
|
||||
* <p>
|
||||
* <b>NOTE:</b> this class assumes the stored integers are doc Ids (hence why it
|
||||
* extends {@link DocIdSet}). Therefore its {@link #iterator()} assumes {@value
|
||||
* DocIdSetIterator#NO_MORE_DOCS} can be used as sentinel. If you intent to use
|
||||
* this value, then make sure it's not used during search flow.
|
||||
*/
|
||||
public class SortedVIntList extends DocIdSet {
|
||||
/** When a BitSet has fewer than 1 in BITS2VINTLIST_SIZE bits set,
|
||||
|
@ -99,8 +104,9 @@ public class SortedVIntList extends DocIdSet {
|
|||
*/
|
||||
public SortedVIntList(DocIdSetIterator docIdSetIterator) throws IOException {
|
||||
SortedVIntListBuilder builder = new SortedVIntListBuilder();
|
||||
while (docIdSetIterator.next()) {
|
||||
builder.addInt(docIdSetIterator.doc());
|
||||
int doc;
|
||||
while ((doc = docIdSetIterator.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
builder.addInt(doc);
|
||||
}
|
||||
builder.done();
|
||||
}
|
||||
|
@ -181,6 +187,7 @@ public class SortedVIntList extends DocIdSet {
|
|||
return new DocIdSetIterator() {
|
||||
int bytePos = 0;
|
||||
int lastInt = 0;
|
||||
int doc = -1;
|
||||
|
||||
private void advance() {
|
||||
// See org.apache.lucene.store.IndexInput.readVInt()
|
||||
|
@ -192,26 +199,43 @@ public class SortedVIntList extends DocIdSet {
|
|||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {return lastInt;}
|
||||
|
||||
public int docID() {
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() {
|
||||
if (bytePos >= lastBytePos) {
|
||||
return false;
|
||||
} else {
|
||||
advance();
|
||||
return true;
|
||||
}
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() {
|
||||
if (bytePos >= lastBytePos) {
|
||||
doc = NO_MORE_DOCS;
|
||||
} else {
|
||||
advance();
|
||||
doc = lastInt;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int docNr) {
|
||||
return advance(docNr) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) {
|
||||
while (bytePos < lastBytePos) {
|
||||
advance();
|
||||
if (lastInt >= docNr) { // No skipping to docNr available.
|
||||
return true;
|
||||
if (lastInt >= target) {
|
||||
return doc = lastInt;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,18 +175,32 @@ final class JustCompileSearch {
|
|||
|
||||
static final class JustCompileDocIdSetIterator extends DocIdSetIterator {
|
||||
|
||||
/** @deprecated delete in 3.0 */
|
||||
public int doc() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0 */
|
||||
public boolean next() throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0 */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileFieldCache implements FieldCache {
|
||||
|
@ -470,6 +484,11 @@ final class JustCompileSearch {
|
|||
super(similarity);
|
||||
}
|
||||
|
||||
protected boolean score(Collector collector, int max, int firstDocID)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
@ -478,18 +497,32 @@ final class JustCompileSearch {
|
|||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0 */
|
||||
public int doc() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int docID() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0. */
|
||||
public boolean next() throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileSimilarity extends Similarity {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package org.apache.lucene.search;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
|
||||
/**
|
||||
|
@ -56,17 +56,17 @@ public class QueryUtils {
|
|||
}
|
||||
|
||||
public static void checkEqual(Query q1, Query q2) {
|
||||
TestCase.assertEquals(q1, q2);
|
||||
TestCase.assertEquals(q1.hashCode(), q2.hashCode());
|
||||
Assert.assertEquals(q1, q2);
|
||||
Assert.assertEquals(q1.hashCode(), q2.hashCode());
|
||||
}
|
||||
|
||||
public static void checkUnequal(Query q1, Query q2) {
|
||||
TestCase.assertTrue(!q1.equals(q2));
|
||||
TestCase.assertTrue(!q2.equals(q1));
|
||||
Assert.assertTrue(!q1.equals(q2));
|
||||
Assert.assertTrue(!q2.equals(q1));
|
||||
|
||||
// possible this test can fail on a hash collision... if that
|
||||
// happens, please change test to use a different example.
|
||||
TestCase.assertTrue(q1.hashCode() != q2.hashCode());
|
||||
Assert.assertTrue(q1.hashCode() != q2.hashCode());
|
||||
}
|
||||
|
||||
/** deep check that explanations of a query 'score' correctly */
|
||||
|
@ -169,8 +169,9 @@ public class QueryUtils {
|
|||
try {
|
||||
int op = order[(opidx[0]++)%order.length];
|
||||
//System.out.println(op==skip_op ? "skip("+(sdoc[0]+1)+")":"next()");
|
||||
boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next();
|
||||
sdoc[0] = scorer.doc();
|
||||
boolean more = op == skip_op ? scorer.advance(sdoc[0] + 1) != DocIdSetIterator.NO_MORE_DOCS
|
||||
: scorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS;
|
||||
sdoc[0] = scorer.docID();
|
||||
float scorerScore = scorer.score();
|
||||
float scorerScore2 = scorer.score();
|
||||
float scoreDiff = Math.abs(score-scorerScore);
|
||||
|
@ -204,8 +205,9 @@ public class QueryUtils {
|
|||
// make sure next call to scorer is false.
|
||||
int op = order[(opidx[0]++)%order.length];
|
||||
//System.out.println(op==skip_op ? "last: skip()":"last: next()");
|
||||
boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next();
|
||||
TestCase.assertFalse(more);
|
||||
boolean more = (op == skip_op ? scorer.advance(sdoc[0] + 1) : scorer
|
||||
.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS;
|
||||
Assert.assertFalse(more);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,11 +230,11 @@ public class QueryUtils {
|
|||
for (int i=lastDoc[0]+1; i<=doc; i++) {
|
||||
Weight w = q.weight(s);
|
||||
Scorer scorer = w.scorer(s.getIndexReader());
|
||||
TestCase.assertTrue("query collected "+doc+" but skipTo("+i+") says no more docs!",scorer.skipTo(i));
|
||||
TestCase.assertEquals("query collected "+doc+" but skipTo("+i+") got to "+scorer.doc(),doc,scorer.doc());
|
||||
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();
|
||||
TestCase.assertEquals("unstable skipTo("+i+") score!",skipToScore,scorer.score(),maxDiff);
|
||||
TestCase.assertEquals("query assigned doc "+doc+" a score of <"+score+"> but skipTo("+i+") has <"+skipToScore+">!",score,skipToScore,maxDiff);
|
||||
Assert.assertEquals("unstable skipTo("+i+") score!",skipToScore,scorer.score(),maxDiff);
|
||||
Assert.assertEquals("query assigned doc "+doc+" a score of <"+score+"> but skipTo("+i+") has <"+skipToScore+">!",score,skipToScore,maxDiff);
|
||||
}
|
||||
lastDoc[0] = doc;
|
||||
} catch (IOException e) {
|
||||
|
@ -245,8 +247,8 @@ public class QueryUtils {
|
|||
});
|
||||
Weight w = q.weight(s);
|
||||
Scorer scorer = w.scorer(s.getIndexReader());
|
||||
boolean more = scorer.skipTo(lastDoc[0]+1);
|
||||
boolean more = scorer.advance(lastDoc[0] + 1) != DocIdSetIterator.NO_MORE_DOCS;
|
||||
if (more)
|
||||
TestCase.assertFalse("query's last doc was "+lastDoc[0]+" but skipTo("+(lastDoc[0]+1)+") got to "+scorer.doc(),more);
|
||||
Assert.assertFalse("query's last doc was "+lastDoc[0]+" but skipTo("+(lastDoc[0]+1)+") got to "+scorer.docID(),more);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,23 +18,18 @@ package org.apache.lucene.search;
|
|||
*/
|
||||
|
||||
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/** Test BooleanQuery2 against BooleanQuery by overriding the standard query parser.
|
||||
* This also tests the scoring order of BooleanQuery.
|
||||
*/
|
||||
|
@ -158,13 +153,14 @@ public class TestBoolean2 extends LuceneTestCase {
|
|||
|
||||
int tot=0;
|
||||
|
||||
BooleanQuery q1 = null;
|
||||
try {
|
||||
|
||||
// increase number of iterations for more complete testing
|
||||
for (int i=0; i<1000; i++) {
|
||||
int level = rnd.nextInt(3);
|
||||
BooleanQuery q1 = randBoolQuery(new Random(rnd.nextLong()), level, field, vals, null);
|
||||
|
||||
q1 = randBoolQuery(new Random(rnd.nextLong()), level, field, vals, null);
|
||||
|
||||
// Can't sort by relevance since floating point numbers may not quite
|
||||
// match up.
|
||||
Sort sort = Sort.INDEXORDER;
|
||||
|
@ -181,6 +177,10 @@ public class TestBoolean2 extends LuceneTestCase {
|
|||
CheckHits.checkEqual(q1, hits1, hits2);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// For easier debugging
|
||||
System.out.println("failed query: " + q1);
|
||||
throw e;
|
||||
} finally { // even when a test fails.
|
||||
BooleanQuery.setAllowDocsOutOfOrder(false);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.lucene.search;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -74,5 +75,41 @@ public class TestBooleanScorer extends LuceneTestCase
|
|||
|
||||
}
|
||||
|
||||
public void testEmptyBucketWithMoreDocs() throws Exception {
|
||||
// This test checks the logic of nextDoc() when all sub scorers have docs
|
||||
// beyond the first bucket (for example). Currently, the code relies on the
|
||||
// 'more' variable to work properly, and this test ensures that if the logic
|
||||
// changes, we have a test to back it up.
|
||||
|
||||
Similarity sim = Similarity.getDefault();
|
||||
Scorer[] scorers = new Scorer[] {new Scorer(sim) {
|
||||
private int doc = -1;
|
||||
public Explanation explain(int doc) throws IOException { return null; }
|
||||
public float score() throws IOException { return 0; }
|
||||
/** @deprecated delete in 3.0. */
|
||||
public int doc() { return 3000; }
|
||||
public int docID() { return doc; }
|
||||
/** @deprecated delete in 3.0 */
|
||||
public boolean next() throws IOException { return nextDoc() != NO_MORE_DOCS; }
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return doc = doc == -1 ? 3000 : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated delete in 3.0 */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
return doc = target <= 3000 ? 3000 : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
}};
|
||||
BooleanScorer bs = new BooleanScorer(sim, 1, Arrays.asList(scorers), null);
|
||||
|
||||
assertEquals("should have received 3000", 3000, bs.nextDoc());
|
||||
assertEquals("should have received NO_MORE_DOCS", DocIdSetIterator.NO_MORE_DOCS, bs.nextDoc());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -136,10 +136,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase{
|
|||
|
||||
final Weight dw = dq.weight(s);
|
||||
final Scorer ds = dw.scorer(r);
|
||||
final boolean skipOk = ds.skipTo(3);
|
||||
final boolean skipOk = ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS;
|
||||
if (skipOk) {
|
||||
fail("firsttime skipTo found a match? ... " +
|
||||
r.document(ds.doc()).get("id"));
|
||||
fail("firsttime skipTo found a match? ... " + r.document(ds.docID()).get("id"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,8 +151,8 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase{
|
|||
|
||||
final Weight dw = dq.weight(s);
|
||||
final Scorer ds = dw.scorer(r);
|
||||
assertTrue("firsttime skipTo found no match", ds.skipTo(3));
|
||||
assertEquals("found wrong docid", "d4", r.document(ds.doc()).get("id"));
|
||||
assertTrue("firsttime skipTo found no match", ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertEquals("found wrong docid", "d4", r.document(ds.docID()).get("id"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,27 +34,37 @@ public class TestDocIdSet extends LuceneTestCase {
|
|||
public DocIdSetIterator iterator() {
|
||||
return new DocIdSetIterator() {
|
||||
|
||||
int docid=-1;
|
||||
//@Override
|
||||
int docid = -1;
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() {
|
||||
return docid;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public int docID() {
|
||||
return docid;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
docid++;
|
||||
return (docid<maxdoc);
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
do {
|
||||
if (!next()) {
|
||||
return false;
|
||||
}
|
||||
} while (target > doc());
|
||||
public int nextDoc() throws IOException {
|
||||
docid++;
|
||||
return docid < maxdoc ? docid : (docid = NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
return true;
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public int advance(int target) throws IOException {
|
||||
while (nextDoc() < target) {}
|
||||
return docid;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -70,10 +80,11 @@ public class TestDocIdSet extends LuceneTestCase {
|
|||
|
||||
DocIdSetIterator iter = filteredSet.iterator();
|
||||
ArrayList/*<Integer>*/ list = new ArrayList/*<Integer>*/();
|
||||
if (iter.skipTo(3)) {
|
||||
list.add(new Integer(iter.doc()));
|
||||
while(iter.next()) {
|
||||
list.add(new Integer(iter.doc()));
|
||||
int doc = iter.advance(3);
|
||||
if (doc != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
list.add(Integer.valueOf(doc));
|
||||
while((doc = iter.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
list.add(Integer.valueOf(doc));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,15 +36,28 @@ public class TestPositiveScoresOnlyCollector extends LuceneTestCase {
|
|||
return idx == scores.length ? Float.NaN : scores[idx];
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return idx; }
|
||||
|
||||
public int docID() { return idx; }
|
||||
|
||||
public boolean next() throws IOException {
|
||||
return ++idx == scores.length;
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int nextDoc() throws IOException {
|
||||
return ++idx != scores.length ? idx : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
idx = target;
|
||||
return idx >= scores.length;
|
||||
return idx < scores.length ? idx : NO_MORE_DOCS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +84,7 @@ public class TestPositiveScoresOnlyCollector extends LuceneTestCase {
|
|||
TopDocsCollector tdc = TopScoreDocCollector.create(scores.length, true);
|
||||
Collector c = new PositiveScoresOnlyCollector(tdc);
|
||||
c.setScorer(s);
|
||||
while (!s.next()) {
|
||||
while (s.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
c.collect(0);
|
||||
}
|
||||
TopDocs td = tdc.topDocs();
|
||||
|
|
|
@ -42,16 +42,30 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
|
|||
return idx == scores.length ? Float.NaN : scores[idx++];
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #docID()} instead. */
|
||||
public int doc() { return doc; }
|
||||
|
||||
public int docID() { return doc; }
|
||||
|
||||
/** @deprecated use {@link #nextDoc()} instead. */
|
||||
public boolean next() throws IOException {
|
||||
return ++doc == scores.length;
|
||||
return nextDoc() != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
doc = target;
|
||||
return doc >= scores.length;
|
||||
public int nextDoc() throws IOException {
|
||||
return ++doc < scores.length ? doc : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #advance(int)} instead. */
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
return advance(target) != NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
public int advance(int target) throws IOException {
|
||||
doc = target;
|
||||
return doc < scores.length ? doc : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class ScoreCachingCollector extends Collector {
|
||||
|
@ -98,8 +112,9 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
|
|||
scc.setScorer(s);
|
||||
|
||||
// We need to iterate on the scorer so that its doc() advances.
|
||||
while (!s.next()) {
|
||||
scc.collect(s.doc());
|
||||
int doc;
|
||||
while ((doc = s.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
scc.collect(doc);
|
||||
}
|
||||
|
||||
for (int i = 0; i < scores.length; i++) {
|
||||
|
|
|
@ -16,7 +16,9 @@ package org.apache.lucene.search;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.analysis.SimpleAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
|
@ -27,10 +29,7 @@ import org.apache.lucene.search.spans.SpanTermQuery;
|
|||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.util.English;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestSpanQueryFilter extends LuceneTestCase {
|
||||
|
||||
|
@ -77,7 +76,7 @@ public class TestSpanQueryFilter extends LuceneTestCase {
|
|||
int getDocIdSetSize(DocIdSet docIdSet) throws Exception {
|
||||
int size = 0;
|
||||
DocIdSetIterator it = docIdSet.iterator();
|
||||
while (it.next()) {
|
||||
while (it.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) {
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
|
@ -85,7 +84,7 @@ public class TestSpanQueryFilter extends LuceneTestCase {
|
|||
|
||||
public void assertContainsDocId(String msg, DocIdSet docIdSet, int docId) throws Exception {
|
||||
DocIdSetIterator it = docIdSet.iterator();
|
||||
assertTrue(msg, it.skipTo(docId));
|
||||
assertTrue(msg, it.doc() == docId);
|
||||
assertTrue(msg, it.advance(docId) != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertTrue(msg, it.docID() == docId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,11 +134,11 @@ public class TestTermScorer extends LuceneTestCase
|
|||
TermScorer ts = new TermScorer(weight,
|
||||
indexReader.termDocs(allTerm), indexSearcher.getSimilarity(),
|
||||
indexReader.norms(FIELD));
|
||||
assertTrue("next did not return a doc", ts.next() == true);
|
||||
assertTrue("next did not return a doc", ts.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertTrue("score is not correct", ts.score() == 1.6931472f);
|
||||
assertTrue("next did not return a doc", ts.next() == true);
|
||||
assertTrue("next did not return a doc", ts.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertTrue("score is not correct", ts.score() == 1.6931472f);
|
||||
assertTrue("next returned a doc and it should not have", ts.next() == false);
|
||||
assertTrue("next returned a doc and it should not have", ts.nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
public void testSkipTo() throws Exception {
|
||||
|
@ -151,7 +151,7 @@ public class TestTermScorer extends LuceneTestCase
|
|||
TermScorer ts = new TermScorer(weight,
|
||||
indexReader.termDocs(allTerm), indexSearcher.getSimilarity(),
|
||||
indexReader.norms(FIELD));
|
||||
assertTrue("Didn't skip", ts.skipTo(3) == true);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import java.io.IOException;
|
|||
import java.util.Collection;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.Similarity;
|
||||
import org.apache.lucene.search.Weight;
|
||||
|
||||
/**
|
||||
* Holds all implementations of classes in the o.a.l.s.spans package as a
|
||||
|
@ -109,4 +111,15 @@ final class JustCompileSearchSpans {
|
|||
|
||||
}
|
||||
|
||||
static final class JustCompileSpanScorer extends SpanScorer {
|
||||
|
||||
protected JustCompileSpanScorer(Spans spans, Weight weight,
|
||||
Similarity similarity, byte[] norms) throws IOException {
|
||||
super(spans, weight, similarity, norms);
|
||||
}
|
||||
|
||||
protected boolean setFreqCurrentDoc() throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,8 +165,7 @@ public class TestNearSpansOrdered extends LuceneTestCase {
|
|||
SpanNearQuery q = makeQuery();
|
||||
Weight w = q.createWeight(searcher);
|
||||
Scorer s = w.scorer(searcher.getIndexReader());
|
||||
assertEquals(true, s.skipTo(1));
|
||||
assertEquals(1, s.doc());
|
||||
assertEquals(1, s.advance(1));
|
||||
}
|
||||
/**
|
||||
* not a direct test of NearSpans, but a demonstration of how/when
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.lucene.search.spans;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.CheckHits;
|
||||
|
@ -392,11 +393,11 @@ public class TestSpans extends LuceneTestCase {
|
|||
|
||||
Scorer spanScorer = snq.weight(searcher).scorer(searcher.getIndexReader());
|
||||
|
||||
assertTrue("first doc", spanScorer.next());
|
||||
assertEquals("first doc number", spanScorer.doc(), 11);
|
||||
assertTrue("first doc", spanScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertEquals("first doc number", spanScorer.docID(), 11);
|
||||
float score = spanScorer.score();
|
||||
assertTrue("first doc score should be zero, " + score, score == 0.0f);
|
||||
assertTrue("no second doc", ! spanScorer.next());
|
||||
assertTrue("no second doc", spanScorer.nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
// LUCENE-1404
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.lucene.util;
|
|||
import java.util.Random;
|
||||
import java.util.BitSet;
|
||||
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
|
||||
/**
|
||||
* @version $Id$
|
||||
*/
|
||||
|
@ -55,12 +57,8 @@ public class TestOpenBitSet extends LuceneTestCase {
|
|||
OpenBitSetIterator iterator = new OpenBitSetIterator(b);
|
||||
do {
|
||||
aa = a.nextSetBit(aa+1);
|
||||
if (rand.nextBoolean())
|
||||
iterator.next();
|
||||
else
|
||||
iterator.skipTo(bb+1);
|
||||
bb = iterator.doc();
|
||||
assertEquals(aa,bb);
|
||||
bb = rand.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1);
|
||||
assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb);
|
||||
} while (aa>=0);
|
||||
}
|
||||
|
||||
|
@ -69,11 +67,8 @@ public class TestOpenBitSet extends LuceneTestCase {
|
|||
OpenBitSetIterator iterator = new OpenBitSetIterator(b);
|
||||
do {
|
||||
aa = a.nextSetBit(aa+1);
|
||||
if (rand.nextBoolean())
|
||||
bb = iterator.nextDoc();
|
||||
else
|
||||
bb = iterator.next(bb+1);
|
||||
assertEquals(aa,bb);
|
||||
bb = rand.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1);
|
||||
assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb);
|
||||
} while (aa>=0);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ public class TestSortedVIntList extends TestCase {
|
|||
}
|
||||
DocIdSetIterator m = vintList.iterator();
|
||||
for (int i = 0; i < ints.length; i++) {
|
||||
assertTrue("No end of Matcher at: " + i, m.next());
|
||||
assertEquals(ints[i], m.doc());
|
||||
assertTrue("No end of Matcher at: " + i, m.nextDoc() != DocIdSetIterator.NO_MORE_DOCS);
|
||||
assertEquals(ints[i], m.docID());
|
||||
}
|
||||
assertTrue("End of Matcher", (! m.next()));
|
||||
assertTrue("End of Matcher", m.nextDoc() == DocIdSetIterator.NO_MORE_DOCS);
|
||||
}
|
||||
|
||||
void tstVIntList(
|
||||
|
@ -143,9 +143,6 @@ public class TestSortedVIntList extends TestCase {
|
|||
public void test02() {
|
||||
tstInts(new int[] {0});
|
||||
}
|
||||
public void test03() {
|
||||
tstInts(new int[] {0,Integer.MAX_VALUE});
|
||||
}
|
||||
public void test04a() {
|
||||
tstInts(new int[] {0, VB2 - 1});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue