mirror of https://github.com/apache/lucene.git
LUCENE-4607: add DISI/Spans.cost
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1456670 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d7a71a3a29
commit
2c64eb9019
|
@ -76,6 +76,9 @@ New Features
|
|||
* LUCENE-4827: Add additional ctor to PostingsHighlighter PassageScorer
|
||||
to provide bm25 k1,b,avgdl parameters. (Robert Muir)
|
||||
|
||||
* LUCENE-4607: Add DocIDSetIterator.cost() and Spans.cost() for optimizing
|
||||
scoring. (Simon Willnauer, Robert Muir)
|
||||
|
||||
Optimizations
|
||||
|
||||
* LUCENE-4819: Added Sorted[Set]DocValues.termsEnum(), and optimized the
|
||||
|
|
|
@ -1488,6 +1488,11 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
}
|
||||
return docID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return postings.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Docs + freqs:
|
||||
|
@ -1553,6 +1558,11 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
}
|
||||
return docID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return postings.length / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Docs + freqs + positions/offets:
|
||||
|
@ -1634,6 +1644,12 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
}
|
||||
return docID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
// TODO: could do a better estimate
|
||||
return postings.length / 2;
|
||||
}
|
||||
}
|
||||
|
||||
private final static class LowFreqDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -1786,6 +1802,12 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
// TODO: could do a better estimate
|
||||
return postings.length / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Docs + freqs:
|
||||
|
@ -1959,6 +1981,11 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
return docID = docIDs[upto];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docIDs.length;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: specialize offsets and not
|
||||
|
@ -2192,5 +2219,10 @@ public final class DirectPostingsFormat extends PostingsFormat {
|
|||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docIDs.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -431,6 +431,11 @@ public final class MemoryPostingsFormat extends PostingsFormat {
|
|||
public int freq() {
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return numDocs;
|
||||
}
|
||||
}
|
||||
|
||||
private final static class FSTDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -618,6 +623,11 @@ public final class MemoryPostingsFormat extends PostingsFormat {
|
|||
public int freq() {
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return numDocs;
|
||||
}
|
||||
}
|
||||
|
||||
private final static class FSTTermsEnum extends TermsEnum {
|
||||
|
|
|
@ -260,6 +260,7 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
private int accum;
|
||||
private int freq;
|
||||
private int payloadLength;
|
||||
private int cost;
|
||||
|
||||
public PulsingDocsEnum(FieldInfo fieldInfo) {
|
||||
indexOptions = fieldInfo.getIndexOptions();
|
||||
|
@ -283,6 +284,7 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
docID = -1;
|
||||
accum = 0;
|
||||
freq = 1;
|
||||
cost = termState.docFreq;
|
||||
payloadLength = 0;
|
||||
this.liveDocs = liveDocs;
|
||||
return this;
|
||||
|
@ -367,6 +369,11 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
}
|
||||
return docID = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PulsingDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -390,6 +397,7 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
private int offsetLength;
|
||||
|
||||
private boolean payloadRetrieved;
|
||||
private int cost;
|
||||
|
||||
public PulsingDocsAndPositionsEnum(FieldInfo fieldInfo) {
|
||||
indexOptions = fieldInfo.getIndexOptions();
|
||||
|
@ -415,6 +423,7 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
posPending = 0;
|
||||
docID = -1;
|
||||
accum = 0;
|
||||
cost = termState.docFreq;
|
||||
startOffset = storeOffsets ? 0 : -1; // always return -1 if no offsets are stored
|
||||
offsetLength = 0;
|
||||
//System.out.println("PR d&p reset storesPayloads=" + storePayloads + " bytes=" + bytes.length + " this=" + this);
|
||||
|
@ -551,6 +560,11 @@ public class PulsingPostingsReader extends PostingsReaderBase {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -441,6 +441,11 @@ public class SepPostingsReader extends PostingsReaderBase {
|
|||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
|
||||
class SepDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -717,5 +722,10 @@ public class SepPostingsReader extends PostingsReaderBase {
|
|||
pendingPayloadBytes = 0;
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
} else {
|
||||
docsEnum = new SimpleTextDocsEnum();
|
||||
}
|
||||
return docsEnum.reset(docsStart, liveDocs, indexOptions == IndexOptions.DOCS_ONLY);
|
||||
return docsEnum.reset(docsStart, liveDocs, indexOptions == IndexOptions.DOCS_ONLY, docFreq);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -216,7 +216,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
} else {
|
||||
docsAndPositionsEnum = new SimpleTextDocsAndPositionsEnum();
|
||||
}
|
||||
return docsAndPositionsEnum.reset(docsStart, liveDocs, indexOptions);
|
||||
return docsAndPositionsEnum.reset(docsStart, liveDocs, indexOptions, docFreq);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -234,6 +234,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
private Bits liveDocs;
|
||||
private final BytesRef scratch = new BytesRef(10);
|
||||
private final CharsRef scratchUTF16 = new CharsRef(10);
|
||||
private int cost;
|
||||
|
||||
public SimpleTextDocsEnum() {
|
||||
this.inStart = SimpleTextFieldsReader.this.in;
|
||||
|
@ -244,12 +245,13 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
return in == inStart;
|
||||
}
|
||||
|
||||
public SimpleTextDocsEnum reset(long fp, Bits liveDocs, boolean omitTF) throws IOException {
|
||||
public SimpleTextDocsEnum reset(long fp, Bits liveDocs, boolean omitTF, int docFreq) throws IOException {
|
||||
this.liveDocs = liveDocs;
|
||||
in.seek(fp);
|
||||
this.omitTF = omitTF;
|
||||
docID = -1;
|
||||
tf = 1;
|
||||
cost = docFreq;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -316,6 +318,11 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
while(nextDoc() < target);
|
||||
return docID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleTextDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -334,6 +341,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
private boolean readPositions;
|
||||
private int startOffset;
|
||||
private int endOffset;
|
||||
private int cost;
|
||||
|
||||
public SimpleTextDocsAndPositionsEnum() {
|
||||
this.inStart = SimpleTextFieldsReader.this.in;
|
||||
|
@ -344,7 +352,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
return in == inStart;
|
||||
}
|
||||
|
||||
public SimpleTextDocsAndPositionsEnum reset(long fp, Bits liveDocs, IndexOptions indexOptions) {
|
||||
public SimpleTextDocsAndPositionsEnum reset(long fp, Bits liveDocs, IndexOptions indexOptions, int docFreq) {
|
||||
this.liveDocs = liveDocs;
|
||||
nextDocStart = fp;
|
||||
docID = -1;
|
||||
|
@ -354,6 +362,7 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
startOffset = -1;
|
||||
endOffset = -1;
|
||||
}
|
||||
cost = docFreq;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -471,6 +480,11 @@ class SimpleTextFieldsReader extends FieldsProducer {
|
|||
public BytesRef getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
static class TermData {
|
||||
|
|
|
@ -444,6 +444,11 @@ public class SimpleTextTermVectorsReader extends TermVectorsReader {
|
|||
this.doc = -1;
|
||||
didNext = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SimpleTVDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -535,5 +540,10 @@ public class SimpleTextTermVectorsReader extends TermVectorsReader {
|
|||
return endOffsets[nextPos-1];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,5 +134,14 @@ public final class MappingMultiDocsAndPositionsEnum extends DocsAndPositionsEnum
|
|||
public BytesRef getPayload() throws IOException {
|
||||
return current.getPayload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long cost = 0;
|
||||
for (EnumWithSlice enumWithSlice : subs) {
|
||||
cost += enumWithSlice.docsAndPositionsEnum.cost();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,5 +114,14 @@ public final class MappingMultiDocsEnum extends DocsEnum {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long cost = 0;
|
||||
for (EnumWithSlice enumWithSlice : subs) {
|
||||
cost += enumWithSlice.docsEnum.cost();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1037,6 +1037,10 @@ public final class CompressingTermVectorsReader extends TermVectorsReader implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int sum(int[] arr) {
|
||||
|
|
|
@ -513,6 +513,11 @@ public class Lucene40PostingsReader extends PostingsReaderBase {
|
|||
}
|
||||
return scanTo(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return limit;
|
||||
}
|
||||
}
|
||||
|
||||
private final class AllDocsSegmentDocsEnum extends SegmentDocsEnumBase {
|
||||
|
@ -886,6 +891,11 @@ public class Lucene40PostingsReader extends PostingsReaderBase {
|
|||
public BytesRef getPayload() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return limit;
|
||||
}
|
||||
}
|
||||
|
||||
// Decodes docs & positions & (payloads and/or offsets)
|
||||
|
@ -1179,5 +1189,10 @@ public class Lucene40PostingsReader extends PostingsReaderBase {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -619,6 +619,11 @@ public class Lucene40TermVectorsReader extends TermVectorsReader implements Clos
|
|||
this.doc = -1;
|
||||
didNext = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TVDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -726,6 +731,11 @@ public class Lucene40TermVectorsReader extends TermVectorsReader implements Clos
|
|||
return endOffsets[nextPos-1];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -599,6 +599,11 @@ public final class Lucene41PostingsReader extends PostingsReaderBase {
|
|||
return nextDoc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1010,6 +1015,11 @@ public final class Lucene41PostingsReader extends PostingsReaderBase {
|
|||
public BytesRef getPayload() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
|
||||
// Also handles payloads + offsets
|
||||
|
@ -1588,5 +1598,10 @@ public final class Lucene41PostingsReader extends PostingsReaderBase {
|
|||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,6 +251,11 @@ public class FilterAtomicReader extends AtomicReader {
|
|||
public AttributeSource attributes() {
|
||||
return in.attributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return in.cost();
|
||||
}
|
||||
}
|
||||
|
||||
/** Base class for filtering {@link DocsAndPositionsEnum} implementations. */
|
||||
|
@ -310,6 +315,11 @@ public class FilterAtomicReader extends AtomicReader {
|
|||
public AttributeSource attributes() {
|
||||
return in.attributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return in.cost();
|
||||
}
|
||||
}
|
||||
|
||||
/** The underlying AtomicReader. */
|
||||
|
|
|
@ -169,6 +169,15 @@ public final class MultiDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long cost = 0;
|
||||
for (int i = 0; i < numSubs; i++) {
|
||||
cost += subs[i].docsAndPositionsEnum.cost();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MultiDocsAndPositionsEnum(" + Arrays.toString(getSubs()) + ")";
|
||||
|
|
|
@ -130,6 +130,15 @@ public final class MultiDocsEnum extends DocsEnum {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long cost = 0;
|
||||
for (int i = 0; i < numSubs; i++) {
|
||||
cost += subs[i].docsEnum.cost();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
// TODO: implement bulk read more efficiently than super
|
||||
/** Holds a {@link DocsEnum} along with the
|
||||
* corresponding {@link ReaderSlice}. */
|
||||
|
|
|
@ -21,15 +21,10 @@ import java.io.IOException;
|
|||
import java.util.*;
|
||||
|
||||
import org.apache.lucene.index.AtomicReaderContext;
|
||||
import org.apache.lucene.index.DocsEnum;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.search.ConjunctionTermScorer.DocsAndFreqs;
|
||||
import org.apache.lucene.search.TermQuery.TermWeight;
|
||||
import org.apache.lucene.search.similarities.Similarity;
|
||||
import org.apache.lucene.search.similarities.Similarity.ExactSimScorer;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
|
@ -174,24 +169,18 @@ public class BooleanQuery extends Query implements Iterable<BooleanClause> {
|
|||
protected ArrayList<Weight> weights;
|
||||
protected int maxCoord; // num optional + num required
|
||||
private final boolean disableCoord;
|
||||
private final boolean termConjunction;
|
||||
|
||||
public BooleanWeight(IndexSearcher searcher, boolean disableCoord)
|
||||
throws IOException {
|
||||
this.similarity = searcher.getSimilarity();
|
||||
this.disableCoord = disableCoord;
|
||||
weights = new ArrayList<Weight>(clauses.size());
|
||||
boolean termConjunction = clauses.isEmpty() || minNrShouldMatch != 0 ? false : true;
|
||||
for (int i = 0 ; i < clauses.size(); i++) {
|
||||
BooleanClause c = clauses.get(i);
|
||||
Weight w = c.getQuery().createWeight(searcher);
|
||||
if (!(c.isRequired() && (w instanceof TermWeight))) {
|
||||
termConjunction = false;
|
||||
}
|
||||
weights.add(w);
|
||||
if (!c.isProhibited()) maxCoord++;
|
||||
}
|
||||
this.termConjunction = termConjunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -310,10 +299,6 @@ public class BooleanQuery extends Query implements Iterable<BooleanClause> {
|
|||
public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
|
||||
boolean topScorer, Bits acceptDocs)
|
||||
throws IOException {
|
||||
if (termConjunction) {
|
||||
// specialized scorer for term conjunctions
|
||||
return createConjunctionTermScorer(context, acceptDocs);
|
||||
}
|
||||
List<Scorer> required = new ArrayList<Scorer>();
|
||||
List<Scorer> prohibited = new ArrayList<Scorer>();
|
||||
List<Scorer> optional = new ArrayList<Scorer>();
|
||||
|
@ -356,32 +341,15 @@ public class BooleanQuery extends Query implements Iterable<BooleanClause> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (optional.size() == 0 && prohibited.size() == 0) {
|
||||
float coord = disableCoord ? 1.0f : coord(required.size(), maxCoord);
|
||||
return new ConjunctionScorer(this, required.toArray(new Scorer[required.size()]), coord);
|
||||
}
|
||||
|
||||
// Return a BooleanScorer2
|
||||
return new BooleanScorer2(this, disableCoord, minNrShouldMatch, required, prohibited, optional, maxCoord);
|
||||
}
|
||||
|
||||
private Scorer createConjunctionTermScorer(AtomicReaderContext context, Bits acceptDocs)
|
||||
throws IOException {
|
||||
|
||||
// TODO: fix scorer API to specify "needsScores" up
|
||||
// front, so we can do match-only if caller doesn't
|
||||
// needs scores
|
||||
|
||||
final DocsAndFreqs[] docsAndFreqs = new DocsAndFreqs[weights.size()];
|
||||
for (int i = 0; i < docsAndFreqs.length; i++) {
|
||||
final TermWeight weight = (TermWeight) weights.get(i);
|
||||
final Scorer scorer = weight.scorer(context, true, false, acceptDocs);
|
||||
if (scorer == null) {
|
||||
return null;
|
||||
} else {
|
||||
assert scorer instanceof TermScorer;
|
||||
docsAndFreqs[i] = new DocsAndFreqs((TermScorer) scorer);
|
||||
}
|
||||
}
|
||||
return new ConjunctionTermScorer(this, disableCoord ? 1.0f : coord(
|
||||
docsAndFreqs.length, docsAndFreqs.length), docsAndFreqs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean scoresDocsOutOfOrder() {
|
||||
for (BooleanClause c : clauses) {
|
||||
|
|
|
@ -135,6 +135,9 @@ final class BooleanScorer extends Scorer {
|
|||
@Override
|
||||
public float score() { return (float)score; }
|
||||
|
||||
@Override
|
||||
public long cost() { return 1; }
|
||||
|
||||
}
|
||||
|
||||
static final class Bucket {
|
||||
|
@ -326,6 +329,11 @@ final class BooleanScorer extends Scorer {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void score(Collector collector) throws IOException {
|
||||
score(collector, Integer.MAX_VALUE, -1);
|
||||
|
|
|
@ -147,6 +147,11 @@ class BooleanScorer2 extends Scorer {
|
|||
public int advance(int target) throws IOException {
|
||||
return scorer.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
private Scorer countingDisjunctionSumScorer(final List<Scorer> scorers,
|
||||
|
@ -175,7 +180,7 @@ class BooleanScorer2 extends Scorer {
|
|||
List<Scorer> requiredScorers) throws IOException {
|
||||
// each scorer from the list counted as a single matcher
|
||||
final int requiredNrMatchers = requiredScorers.size();
|
||||
return new ConjunctionScorer(weight, requiredScorers) {
|
||||
return new ConjunctionScorer(weight, requiredScorers.toArray(new Scorer[requiredScorers.size()])) {
|
||||
private int lastScoredDoc = -1;
|
||||
// Save the score of lastScoredDoc, so that we don't compute it more than
|
||||
// once in score().
|
||||
|
@ -200,7 +205,7 @@ class BooleanScorer2 extends Scorer {
|
|||
|
||||
private Scorer dualConjunctionSumScorer(boolean disableCoord,
|
||||
Scorer req1, Scorer req2) throws IOException { // non counting.
|
||||
return new ConjunctionScorer(weight, req1, req2);
|
||||
return new ConjunctionScorer(weight, new Scorer[] { req1, req2 });
|
||||
// All scorers match, so defaultSimilarity always has 1 as
|
||||
// the coordination factor.
|
||||
// Therefore the sum of the scores of two scorers
|
||||
|
@ -322,6 +327,11 @@ class BooleanScorer2 extends Scorer {
|
|||
return doc = countingSumScorer.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return countingSumScorer.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChildScorer> getChildren() {
|
||||
ArrayList<ChildScorer> children = new ArrayList<ChildScorer>();
|
||||
|
|
|
@ -89,6 +89,9 @@ public abstract class CachingCollector extends Collector {
|
|||
|
||||
@Override
|
||||
public final int nextDoc() { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public long cost() { return 1; }
|
||||
}
|
||||
|
||||
// A CachingCollector which caches scores
|
||||
|
|
|
@ -17,99 +17,76 @@ package org.apache.lucene.search;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
|
||||
/** Scorer for conjunctions, sets of queries, all of which are required. */
|
||||
class ConjunctionScorer extends Scorer {
|
||||
protected int lastDoc = -1;
|
||||
protected final DocsAndFreqs[] docsAndFreqs;
|
||||
private final DocsAndFreqs lead;
|
||||
private final float coord;
|
||||
|
||||
private final Scorer[] scorers;
|
||||
private int lastDoc = -1;
|
||||
|
||||
public ConjunctionScorer(Weight weight, Collection<Scorer> scorers) throws IOException {
|
||||
this(weight, scorers.toArray(new Scorer[scorers.size()]));
|
||||
ConjunctionScorer(Weight weight, Scorer[] scorers) {
|
||||
this(weight, scorers, 1f);
|
||||
}
|
||||
|
||||
public ConjunctionScorer(Weight weight, Scorer... scorers) throws IOException {
|
||||
ConjunctionScorer(Weight weight, Scorer[] scorers, float coord) {
|
||||
super(weight);
|
||||
this.scorers = scorers;
|
||||
|
||||
this.coord = coord;
|
||||
this.docsAndFreqs = new DocsAndFreqs[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;
|
||||
docsAndFreqs[i] = new DocsAndFreqs(scorers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 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!
|
||||
// Also we use mergeSort here to be stable (so order of Scoreres that
|
||||
// match on first document keeps preserved):
|
||||
ArrayUtil.mergeSort(scorers, new Comparator<Scorer>() { // sort the array
|
||||
// Sort the array the first time to allow the least frequent DocsEnum to
|
||||
// lead the matching.
|
||||
ArrayUtil.mergeSort(docsAndFreqs, new Comparator<DocsAndFreqs>() {
|
||||
@Override
|
||||
public int compare(Scorer o1, Scorer o2) {
|
||||
return o1.docID() - o2.docID();
|
||||
public int compare(DocsAndFreqs o1, DocsAndFreqs o2) {
|
||||
return Long.signum(o1.cost - o2.cost);
|
||||
}
|
||||
});
|
||||
|
||||
// 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;
|
||||
lead = docsAndFreqs[0]; // least frequent DocsEnum leads the intersection
|
||||
}
|
||||
|
||||
// If first-time skip distance is any predictor of
|
||||
// scorer sparseness, then we should always try to skip first on
|
||||
// those scorers.
|
||||
// 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;
|
||||
int max = end >> 1;
|
||||
for (int i = 0; i < max; i++) {
|
||||
Scorer tmp = scorers[i];
|
||||
int idx = end - i - 1;
|
||||
scorers[i] = scorers[idx];
|
||||
scorers[idx] = tmp;
|
||||
}
|
||||
}
|
||||
private int doNext(int doc) throws IOException {
|
||||
for(;;) {
|
||||
// doc may already be NO_MORE_DOCS here, but we don't check explicitly
|
||||
// since all scorers should advance to NO_MORE_DOCS, match, then
|
||||
// return that value.
|
||||
advanceHead: for(;;) {
|
||||
for (int i = 1; i < docsAndFreqs.length; i++) {
|
||||
// invariant: docsAndFreqs[i].doc <= doc at this point.
|
||||
|
||||
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;
|
||||
// docsAndFreqs[i].doc may already be equal to doc if we "broke advanceHead"
|
||||
// on the previous iteration and the advance on the lead scorer exactly matched.
|
||||
if (docsAndFreqs[i].doc < doc) {
|
||||
docsAndFreqs[i].doc = docsAndFreqs[i].scorer.advance(doc);
|
||||
|
||||
if (docsAndFreqs[i].doc > doc) {
|
||||
// DocsEnum beyond the current doc - break and advance lead to the new highest doc.
|
||||
doc = docsAndFreqs[i].doc;
|
||||
break advanceHead;
|
||||
}
|
||||
}
|
||||
}
|
||||
// success - all DocsEnums are on the same doc
|
||||
return doc;
|
||||
}
|
||||
// advance head for next iteration
|
||||
doc = lead.doc = lead.scorer.advance(doc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
lead.doc = lead.scorer.advance(target);
|
||||
return lastDoc = doNext(lead.doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -119,36 +96,47 @@ class ConjunctionScorer extends Scorer {
|
|||
|
||||
@Override
|
||||
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();
|
||||
lead.doc = lead.scorer.nextDoc();
|
||||
return lastDoc = doNext(lead.doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float score() throws IOException {
|
||||
// TODO: sum into a double and cast to float if we ever send required clauses to BS1
|
||||
float sum = 0.0f;
|
||||
for (int i = 0; i < scorers.length; i++) {
|
||||
sum += scorers[i].score();
|
||||
for (DocsAndFreqs docs : docsAndFreqs) {
|
||||
sum += docs.scorer.score();
|
||||
}
|
||||
return sum;
|
||||
return sum * coord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
return scorers.length;
|
||||
public int freq() {
|
||||
return docsAndFreqs.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return lead.scorer.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChildScorer> getChildren() {
|
||||
ArrayList<ChildScorer> children = new ArrayList<ChildScorer>(scorers.length);
|
||||
for (Scorer scorer : scorers) {
|
||||
children.add(new ChildScorer(scorer, "MUST"));
|
||||
ArrayList<ChildScorer> children = new ArrayList<ChildScorer>(docsAndFreqs.length);
|
||||
for (DocsAndFreqs docs : docsAndFreqs) {
|
||||
children.add(new ChildScorer(docs.scorer, "MUST"));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
static final class DocsAndFreqs {
|
||||
final long cost;
|
||||
final Scorer scorer;
|
||||
int doc = -1;
|
||||
|
||||
DocsAndFreqs(Scorer scorer) {
|
||||
this.scorer = scorer;
|
||||
this.cost = scorer.cost();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
package org.apache.lucene.search;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.apache.lucene.index.DocsEnum;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
|
||||
/** Scorer for conjunctions, sets of terms, all of which are required. */
|
||||
class ConjunctionTermScorer extends Scorer {
|
||||
protected final float coord;
|
||||
protected int lastDoc = -1;
|
||||
protected final DocsAndFreqs[] docsAndFreqs;
|
||||
private final DocsAndFreqs lead;
|
||||
|
||||
ConjunctionTermScorer(Weight weight, float coord,
|
||||
DocsAndFreqs[] docsAndFreqs) {
|
||||
super(weight);
|
||||
this.coord = coord;
|
||||
this.docsAndFreqs = docsAndFreqs;
|
||||
// Sort the array the first time to allow the least frequent DocsEnum to
|
||||
// lead the matching.
|
||||
ArrayUtil.mergeSort(docsAndFreqs, new Comparator<DocsAndFreqs>() {
|
||||
@Override
|
||||
public int compare(DocsAndFreqs o1, DocsAndFreqs o2) {
|
||||
return o1.docFreq - o2.docFreq;
|
||||
}
|
||||
});
|
||||
|
||||
lead = docsAndFreqs[0]; // least frequent DocsEnum leads the intersection
|
||||
}
|
||||
|
||||
private int doNext(int doc) throws IOException {
|
||||
for(;;) {
|
||||
// doc may already be NO_MORE_DOCS here, but we don't check explicitly
|
||||
// since all scorers should advance to NO_MORE_DOCS, match, then
|
||||
// return that value.
|
||||
advanceHead: for(;;) {
|
||||
for (int i = 1; i < docsAndFreqs.length; i++) {
|
||||
// invariant: docsAndFreqs[i].doc <= doc at this point.
|
||||
|
||||
// docsAndFreqs[i].doc may already be equal to doc if we "broke advanceHead"
|
||||
// on the previous iteration and the advance on the lead scorer exactly matched.
|
||||
if (docsAndFreqs[i].doc < doc) {
|
||||
docsAndFreqs[i].doc = docsAndFreqs[i].docs.advance(doc);
|
||||
|
||||
if (docsAndFreqs[i].doc > doc) {
|
||||
// DocsEnum beyond the current doc - break and advance lead to the new highest doc.
|
||||
doc = docsAndFreqs[i].doc;
|
||||
break advanceHead;
|
||||
}
|
||||
}
|
||||
}
|
||||
// success - all DocsEnums are on the same doc
|
||||
return doc;
|
||||
}
|
||||
// advance head for next iteration
|
||||
doc = lead.doc = lead.docs.advance(doc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
lead.doc = lead.docs.advance(target);
|
||||
return lastDoc = doNext(lead.doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int docID() {
|
||||
return lastDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
lead.doc = lead.docs.nextDoc();
|
||||
return lastDoc = doNext(lead.doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float score() throws IOException {
|
||||
// TODO: sum into a double and cast to float if we ever send required clauses to BS1
|
||||
float sum = 0.0f;
|
||||
for (DocsAndFreqs docs : docsAndFreqs) {
|
||||
sum += docs.scorer.score();
|
||||
}
|
||||
return sum * coord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() {
|
||||
return docsAndFreqs.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChildScorer> getChildren() {
|
||||
ArrayList<ChildScorer> children = new ArrayList<ChildScorer>(docsAndFreqs.length);
|
||||
for (DocsAndFreqs docs : docsAndFreqs) {
|
||||
children.add(new ChildScorer(docs.scorer, "MUST"));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
static final class DocsAndFreqs {
|
||||
final DocsEnum docs;
|
||||
final int docFreq;
|
||||
final Scorer scorer;
|
||||
int doc = -1;
|
||||
|
||||
DocsAndFreqs(TermScorer termScorer) {
|
||||
this(termScorer, termScorer.getDocsEnum(), termScorer.getDocFreq());
|
||||
}
|
||||
|
||||
DocsAndFreqs(Scorer scorer, DocsEnum docs, int docFreq) {
|
||||
this.docs = docs;
|
||||
this.docFreq = docFreq;
|
||||
this.scorer = scorer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -206,6 +206,11 @@ public class ConstantScoreQuery extends Query {
|
|||
return docIdSetIterator.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docIdSetIterator.cost();
|
||||
}
|
||||
|
||||
private Collector wrapCollector(final Collector collector) {
|
||||
return new Collector() {
|
||||
@Override
|
||||
|
|
|
@ -105,4 +105,13 @@ abstract class DisjunctionScorer extends Scorer {
|
|||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long sum = 0;
|
||||
for (int i = 0; i < numScorers; i++) {
|
||||
sum += subScorers[i].cost();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ public abstract class DocIdSet {
|
|||
public int docID() { return NO_MORE_DOCS; }
|
||||
@Override
|
||||
public int nextDoc() { return NO_MORE_DOCS; }
|
||||
@Override
|
||||
public long cost() { return 0; }
|
||||
};
|
||||
|
||||
@Override
|
||||
|
|
|
@ -93,4 +93,12 @@ public abstract class DocIdSetIterator {
|
|||
*/
|
||||
public abstract int advance(int target) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the estimated cost of this {@link DocIdSetIterator}.
|
||||
* <p>
|
||||
* This is generally an upper bound of the number of documents this iterator
|
||||
* might match, but may be a rough heuristic, hardcoded value, or otherwise
|
||||
* completely inaccurate.
|
||||
*/
|
||||
public abstract long cost();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ final class ExactPhraseScorer extends Scorer {
|
|||
private final int[] gens = new int[CHUNK];
|
||||
|
||||
boolean noDocs;
|
||||
private final long cost;
|
||||
|
||||
private final static class ChunkState {
|
||||
final DocsAndPositionsEnum posEnum;
|
||||
|
@ -66,6 +67,9 @@ final class ExactPhraseScorer extends Scorer {
|
|||
|
||||
endMinus1 = postings.length-1;
|
||||
|
||||
// min(cost)
|
||||
cost = postings[0].postings.cost();
|
||||
|
||||
for(int i=0;i<postings.length;i++) {
|
||||
|
||||
// Coarse optimization: advance(target) is fairly
|
||||
|
@ -315,4 +319,9 @@ final class ExactPhraseScorer extends Scorer {
|
|||
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,11 @@ public abstract class FieldCacheDocIdSet extends DocIdSet {
|
|||
}
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
};
|
||||
} else if (acceptDocs instanceof FixedBitSet || acceptDocs instanceof OpenBitSet) {
|
||||
// special case for FixedBitSet / OpenBitSet: use the iterator and filter it
|
||||
|
@ -151,6 +156,11 @@ public abstract class FieldCacheDocIdSet extends DocIdSet {
|
|||
}
|
||||
return doc = NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,4 +82,8 @@ public abstract class FilteredDocIdSetIterator extends DocIdSetIterator {
|
|||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return _innerIter.cost();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,6 +210,11 @@ public class FilteredQuery extends Query {
|
|||
public Collection<ChildScorer> getChildren() {
|
||||
return Collections.singleton(new ChildScorer(scorer, "FILTERED"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -304,6 +309,11 @@ public class FilteredQuery extends Query {
|
|||
public final Collection<ChildScorer> getChildren() {
|
||||
return Collections.singleton(new ChildScorer(scorer, "FILTERED"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return Math.min(primary.cost(), secondary.cost());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO once we have way to figure out if we use RA or LeapFrog we can remove this scorer
|
||||
|
|
|
@ -781,6 +781,11 @@ public class IndexSearcher {
|
|||
public float score() {
|
||||
return score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private final FakeScorer fakeScorer = new FakeScorer();
|
||||
|
|
|
@ -77,6 +77,11 @@ public class MatchAllDocsQuery extends Query {
|
|||
doc = target-1;
|
||||
return nextDoc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
}
|
||||
|
||||
private class MatchAllDocsWeight extends Weight {
|
||||
|
|
|
@ -472,6 +472,7 @@ class UnionDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
private int _freq;
|
||||
private DocsQueue _queue;
|
||||
private IntQueue _posList;
|
||||
private long cost;
|
||||
|
||||
public UnionDocsAndPositionsEnum(Bits liveDocs, AtomicReaderContext context, Term[] terms, Map<Term,TermContext> termContexts, TermsEnum termsEnum) throws IOException {
|
||||
List<DocsAndPositionsEnum> docsEnums = new LinkedList<DocsAndPositionsEnum>();
|
||||
|
@ -488,6 +489,7 @@ class UnionDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
// term does exist, but has no positions
|
||||
throw new IllegalStateException("field \"" + term.field() + "\" was indexed without position data; cannot run PhraseQuery (term=" + term.text() + ")");
|
||||
}
|
||||
cost += postings.cost();
|
||||
docsEnums.add(postings);
|
||||
}
|
||||
|
||||
|
@ -570,4 +572,9 @@ class UnionDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
public final int docID() {
|
||||
return _doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,4 +128,9 @@ class ReqExclScorer extends Scorer {
|
|||
}
|
||||
return doc = toNonExcluded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return reqScorer.cost();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,5 +99,10 @@ class ReqOptSumScorer extends Scorer {
|
|||
children.add(new ChildScorer(optScorer, "SHOULD"));
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return reqScorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,4 +89,9 @@ public class ScoreCachingWrappingScorer extends Scorer {
|
|||
public Collection<ChildScorer> getChildren() {
|
||||
return Collections.singleton(new ChildScorer(scorer, "CACHED"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scorer.cost();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ final class SloppyPhraseScorer extends Scorer {
|
|||
private PhrasePositions[] rptStack; // temporary stack for switching colliding repeating pps
|
||||
|
||||
private int numMatches;
|
||||
private final long cost;
|
||||
|
||||
SloppyPhraseScorer(Weight weight, PhraseQuery.PostingsAndFreq[] postings,
|
||||
int slop, Similarity.SloppySimScorer docScorer) {
|
||||
|
@ -57,6 +58,8 @@ final class SloppyPhraseScorer extends Scorer {
|
|||
this.slop = slop;
|
||||
this.numPostings = postings==null ? 0 : postings.length;
|
||||
pq = new PhraseQueue(postings.length);
|
||||
// min(cost)
|
||||
cost = postings[0].postings.cost();
|
||||
// convert tps to a list of phrase positions.
|
||||
// note: phrase-position differs from term-position in that its position
|
||||
// reflects the phrase offset: pp.pos = tp.pos - offset.
|
||||
|
@ -589,6 +592,11 @@ final class SloppyPhraseScorer extends Scorer {
|
|||
return max.doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return "scorer(" + weight + ")"; }
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.lucene.index.TermsEnum;
|
|||
import org.apache.lucene.search.similarities.Similarity.ExactSimScorer;
|
||||
import org.apache.lucene.search.similarities.Similarity;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
/** A Query that matches documents containing a term.
|
||||
|
@ -85,7 +84,7 @@ public class TermQuery extends Query {
|
|||
}
|
||||
DocsEnum docs = termsEnum.docs(acceptDocs, null);
|
||||
assert docs != null;
|
||||
return new TermScorer(this, docs, similarity.exactSimScorer(stats, context), termsEnum.docFreq());
|
||||
return new TermScorer(this, docs, similarity.exactSimScorer(stats, context));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.apache.lucene.search.similarities.Similarity;
|
|||
final class TermScorer extends Scorer {
|
||||
private final DocsEnum docsEnum;
|
||||
private final Similarity.ExactSimScorer docScorer;
|
||||
private final int docFreq;
|
||||
|
||||
/**
|
||||
* Construct a <code>TermScorer</code>.
|
||||
|
@ -39,14 +38,11 @@ final class TermScorer extends Scorer {
|
|||
* @param docScorer
|
||||
* The </code>Similarity.ExactSimScorer</code> implementation
|
||||
* to be used for score computations.
|
||||
* @param docFreq
|
||||
* per-segment docFreq of this term
|
||||
*/
|
||||
TermScorer(Weight weight, DocsEnum td, Similarity.ExactSimScorer docScorer, int docFreq) {
|
||||
TermScorer(Weight weight, DocsEnum td, Similarity.ExactSimScorer docScorer) {
|
||||
super(weight);
|
||||
this.docScorer = docScorer;
|
||||
this.docsEnum = td;
|
||||
this.docFreq = docFreq;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,21 +85,12 @@ final class TermScorer extends Scorer {
|
|||
return docsEnum.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docsEnum.cost();
|
||||
}
|
||||
|
||||
/** Returns a string representation of this <code>TermScorer</code>. */
|
||||
@Override
|
||||
public String toString() { return "scorer(" + weight + ")"; }
|
||||
|
||||
// TODO: benchmark if the specialized conjunction really benefits
|
||||
// from this, or if instead its from sorting by docFreq, or both
|
||||
|
||||
DocsEnum getDocsEnum() {
|
||||
return docsEnum;
|
||||
}
|
||||
|
||||
// TODO: generalize something like this for scorers?
|
||||
// even this is just an estimation...
|
||||
|
||||
int getDocFreq() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,15 @@ public class NearSpansOrdered extends Spans {
|
|||
return matchPayload.isEmpty() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long minCost = Long.MAX_VALUE;
|
||||
for (int i = 0; i < subSpans.length; i++) {
|
||||
minCost = Math.min(minCost, subSpans[i].cost());
|
||||
}
|
||||
return minCost;
|
||||
}
|
||||
|
||||
// inherit javadocs
|
||||
@Override
|
||||
public boolean next() throws IOException {
|
||||
|
|
|
@ -130,6 +130,11 @@ public class NearSpansUnordered extends Spans {
|
|||
return spans.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return spans.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return spans.toString() + "#" + index; }
|
||||
}
|
||||
|
@ -268,6 +273,15 @@ public class NearSpansUnordered extends Spans {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
long minCost = Long.MAX_VALUE;
|
||||
for (int i = 0; i < subSpans.length; i++) {
|
||||
minCost = Math.min(minCost, subSpans[i].cost());
|
||||
}
|
||||
return minCost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "("+query.toString()+")@"+
|
||||
|
|
|
@ -161,6 +161,11 @@ public class SpanNotQuery extends SpanQuery implements Cloneable {
|
|||
return includeSpans.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return includeSpans.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "spans(" + SpanNotQuery.this.toString() + ")";
|
||||
|
|
|
@ -172,12 +172,14 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
|
|||
|
||||
return new Spans() {
|
||||
private SpanQueue queue = null;
|
||||
private long cost;
|
||||
|
||||
private boolean initSpanQueue(int target) throws IOException {
|
||||
queue = new SpanQueue(clauses.size());
|
||||
Iterator<SpanQuery> i = clauses.iterator();
|
||||
while (i.hasNext()) {
|
||||
Spans spans = i.next().getSpans(context, acceptDocs, termContexts);
|
||||
cost += spans.cost();
|
||||
if ( ((target == -1) && spans.next())
|
||||
|| ((target != -1) && spans.skipTo(target))) {
|
||||
queue.add(spans);
|
||||
|
@ -259,6 +261,11 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
|
|||
:(queue.size()>0?(doc()+":"+start()+"-"+end()):"END"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,11 @@ public abstract class SpanPositionCheckQuery extends SpanQuery implements Clonea
|
|||
return spans.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return spans.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "spans(" + SpanPositionCheckQuery.this.toString() + ")";
|
||||
|
|
|
@ -107,4 +107,9 @@ public class SpanScorer extends Scorer {
|
|||
public float sloppyFreq() throws IOException {
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return spans.cost();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,4 +84,12 @@ public abstract class Spans {
|
|||
*/
|
||||
public abstract boolean isPayloadAvailable() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the estimated cost of this spans.
|
||||
* <p>
|
||||
* This is generally an upper bound of the number of documents this iterator
|
||||
* might match, but may be a rough heuristic, hardcoded value, or otherwise
|
||||
* completely inaccurate.
|
||||
*/
|
||||
public abstract long cost();
|
||||
}
|
||||
|
|
|
@ -99,6 +99,11 @@ public class TermSpans extends Spans {
|
|||
return position + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return postings.cost();
|
||||
}
|
||||
|
||||
// TODO: Remove warning after API has been finalized
|
||||
@Override
|
||||
public Collection<byte[]> getPayload() throws IOException {
|
||||
|
@ -166,6 +171,11 @@ public class TermSpans extends Spans {
|
|||
public boolean isPayloadAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static final TermSpans EMPTY_TERM_SPANS = new EmptyTermSpans();
|
||||
|
|
|
@ -95,5 +95,11 @@ public class DocIdBitSet extends DocIdSet implements Bits {
|
|||
docId = d == -1 ? NO_MORE_DOCS : d;
|
||||
return docId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
// upper bound
|
||||
return bitSet.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,4 +190,8 @@ public class OpenBitSetIterator extends DocIdSetIterator {
|
|||
return curDocId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return words / 64;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,11 @@ final class JustCompileSearch {
|
|||
public int advance(int target) {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileExtendedFieldCacheLongParser implements FieldCache.LongParser {
|
||||
|
@ -200,6 +205,10 @@ final class JustCompileSearch {
|
|||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileQuery extends Query {
|
||||
|
@ -246,6 +255,11 @@ final class JustCompileSearch {
|
|||
public int advance(int target) {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileSimilarity extends Similarity {
|
||||
|
|
|
@ -92,6 +92,10 @@ public class TestBooleanScorer extends LuceneTestCase
|
|||
return doc = target <= 3000 ? 3000 : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}};
|
||||
|
||||
BooleanScorer bs = new BooleanScorer(weight, false, 1, Arrays.asList(scorers), null, scorers.length);
|
||||
|
|
|
@ -47,6 +47,10 @@ public class TestCachingCollector extends LuceneTestCase {
|
|||
@Override
|
||||
public int advance(int target) throws IOException { return 0; }
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoOpCollector extends Collector {
|
||||
|
|
|
@ -59,6 +59,11 @@ public class TestDocIdSet extends LuceneTestCase {
|
|||
while (nextDoc() < target) {}
|
||||
return docid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -536,6 +536,11 @@ public class TestFilteredQuery extends LuceneTestCase {
|
|||
advanceCalled = true;
|
||||
return termDocsEnum.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return termDocsEnum.cost();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,11 @@ public class TestPositiveScoresOnlyCollector extends LuceneTestCase {
|
|||
idx = target;
|
||||
return idx < scores.length ? idx : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scores.length;
|
||||
}
|
||||
}
|
||||
|
||||
// The scores must have positive as well as negative values
|
||||
|
|
|
@ -59,6 +59,10 @@ public class TestScoreCachingWrappingScorer extends LuceneTestCase {
|
|||
return doc < scores.length ? doc : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scores.length;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ScoreCachingCollector extends Collector {
|
||||
|
|
|
@ -76,6 +76,10 @@ final class JustCompileSearchSpans {
|
|||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
static final class JustCompileSpanQuery extends SpanQuery {
|
||||
|
@ -134,6 +138,11 @@ final class JustCompileSearchSpans {
|
|||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class JustCompileSpanScorer extends SpanScorer {
|
||||
|
|
|
@ -167,4 +167,9 @@ public class MultiSpansWrapper extends Spans { // can't be package private due t
|
|||
return current.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return Integer.MAX_VALUE; // just for tests
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -614,6 +614,11 @@ class DrillSidewaysScorer extends Scorer {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return baseScorer.cost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ChildScorer> getChildren() {
|
||||
return Collections.singletonList(new ChildScorer(baseScorer, "MUST"));
|
||||
|
|
|
@ -152,6 +152,11 @@ public class MatchingDocsAsScoredDocIDs implements ScoredDocIDs {
|
|||
return doc + current.context.docBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
throw new UnsupportedOperationException("not supported");
|
||||
|
|
|
@ -162,6 +162,10 @@ public class ScoredDocIdsUtils {
|
|||
return docids[next];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return size;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -298,6 +302,10 @@ public class ScoredDocIdsUtils {
|
|||
return ++next < maxDoc ? next : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -394,6 +402,10 @@ public class ScoredDocIdsUtils {
|
|||
return next < maxDoc ? next : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -117,6 +117,11 @@ public class BlockGroupingCollector extends Collector {
|
|||
public int nextDoc() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class OneGroup {
|
||||
|
|
|
@ -497,6 +497,9 @@ public final class PostingsHighlighter {
|
|||
|
||||
@Override
|
||||
public int advance(int target) throws IOException { return NO_MORE_DOCS; }
|
||||
|
||||
@Override
|
||||
public long cost() { return 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -161,17 +161,20 @@ class TermsIncludingScoreQuery extends Query {
|
|||
return null;
|
||||
}
|
||||
|
||||
// what is the runtime...seems ok?
|
||||
final long cost = context.reader().maxDoc() * terms.size();
|
||||
|
||||
segmentTermsEnum = terms.iterator(segmentTermsEnum);
|
||||
if (scoreDocsInOrder) {
|
||||
if (multipleValuesPerDocument) {
|
||||
return new MVInOrderScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc());
|
||||
return new MVInOrderScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc(), cost);
|
||||
} else {
|
||||
return new SVInOrderScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc());
|
||||
return new SVInOrderScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc(), cost);
|
||||
}
|
||||
} else if (multipleValuesPerDocument) {
|
||||
return new MVInnerScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc());
|
||||
return new MVInnerScorer(this, acceptDocs, segmentTermsEnum, context.reader().maxDoc(), cost);
|
||||
} else {
|
||||
return new SVInnerScorer(this, acceptDocs, segmentTermsEnum);
|
||||
return new SVInnerScorer(this, acceptDocs, segmentTermsEnum, cost);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -183,16 +186,18 @@ class TermsIncludingScoreQuery extends Query {
|
|||
final BytesRef spare = new BytesRef();
|
||||
final Bits acceptDocs;
|
||||
final TermsEnum termsEnum;
|
||||
final long cost;
|
||||
|
||||
int upto;
|
||||
DocsEnum docsEnum;
|
||||
DocsEnum reuse;
|
||||
int scoreUpto;
|
||||
|
||||
SVInnerScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum) {
|
||||
SVInnerScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, long cost) {
|
||||
super(weight);
|
||||
this.acceptDocs = acceptDocs;
|
||||
this.termsEnum = termsEnum;
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -261,6 +266,11 @@ class TermsIncludingScoreQuery extends Query {
|
|||
public int freq() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
// This impl that tracks whether a docid has already been emitted. This check makes sure that docs aren't emitted
|
||||
|
@ -270,8 +280,8 @@ class TermsIncludingScoreQuery extends Query {
|
|||
|
||||
final FixedBitSet alreadyEmittedDocs;
|
||||
|
||||
MVInnerScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc) {
|
||||
super(weight, acceptDocs, termsEnum);
|
||||
MVInnerScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc, long cost) {
|
||||
super(weight, acceptDocs, termsEnum, cost);
|
||||
alreadyEmittedDocs = new FixedBitSet(maxDoc);
|
||||
}
|
||||
|
||||
|
@ -326,15 +336,17 @@ class TermsIncludingScoreQuery extends Query {
|
|||
|
||||
final DocIdSetIterator matchingDocsIterator;
|
||||
final float[] scores;
|
||||
final long cost;
|
||||
|
||||
int currentDoc = -1;
|
||||
|
||||
SVInOrderScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc) throws IOException {
|
||||
SVInOrderScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc, long cost) throws IOException {
|
||||
super(weight);
|
||||
FixedBitSet matchingDocs = new FixedBitSet(maxDoc);
|
||||
this.scores = new float[maxDoc];
|
||||
fillDocsAndScores(matchingDocs, acceptDocs, termsEnum);
|
||||
this.matchingDocsIterator = matchingDocs.iterator();
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
protected void fillDocsAndScores(FixedBitSet matchingDocs, Bits acceptDocs, TermsEnum termsEnum) throws IOException {
|
||||
|
@ -378,13 +390,18 @@ class TermsIncludingScoreQuery extends Query {
|
|||
public int advance(int target) throws IOException {
|
||||
return currentDoc = matchingDocsIterator.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
// This scorer deals with the fact that a document can have more than one score from multiple related documents.
|
||||
class MVInOrderScorer extends SVInOrderScorer {
|
||||
|
||||
MVInOrderScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc) throws IOException {
|
||||
super(weight, acceptDocs, termsEnum, maxDoc);
|
||||
MVInOrderScorer(Weight weight, Bits acceptDocs, TermsEnum termsEnum, int maxDoc, long cost) throws IOException {
|
||||
super(weight, acceptDocs, termsEnum, maxDoc, cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -301,6 +301,11 @@ public class ToChildBlockJoinQuery extends Query {
|
|||
}
|
||||
return childDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return parentScorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -347,6 +347,11 @@ public class ToParentBlockJoinCollector extends Collector {
|
|||
public int nextDoc() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private OneGroup[] sortedGroups;
|
||||
|
|
|
@ -409,6 +409,10 @@ public class ToParentBlockJoinQuery extends Query {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return childScorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1020,6 +1020,11 @@ public class MemoryIndex {
|
|||
public int freq() throws IOException {
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private class MemoryDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -1100,6 +1105,11 @@ public class MemoryIndex {
|
|||
public BytesRef getPayload() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -348,6 +348,11 @@ public class CustomScoreQuery extends Query {
|
|||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return subQueryScorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -188,6 +188,11 @@ public class BoostedQuery extends Query {
|
|||
res.addDetail(vals.explain(doc));
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return scorer.cost();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -158,6 +158,11 @@ public class FunctionQuery extends Query {
|
|||
return score>Float.NEGATIVE_INFINITY ? score : -Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
return 1;
|
||||
|
|
|
@ -91,4 +91,9 @@ public class ValueSourceScorer extends Scorer {
|
|||
public int freq() throws IOException {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,11 @@ public class TFValueSource extends TermFreqValueSource {
|
|||
public int advance(int target) {
|
||||
return DocIdSetIterator.NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
atDoc = -1;
|
||||
|
|
|
@ -90,6 +90,11 @@ public class TermFreqValueSource extends DocFreqValueSource {
|
|||
public int advance(int target) {
|
||||
return DocIdSetIterator.NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
atDoc = -1;
|
||||
|
|
|
@ -433,6 +433,11 @@ public final class RAMOnlyPostingsFormat extends PostingsFormat {
|
|||
public int docID() {
|
||||
return current.docID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return ramTerm.docs.size();
|
||||
}
|
||||
}
|
||||
|
||||
private static class RAMDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||
|
@ -505,6 +510,11 @@ public final class RAMOnlyPostingsFormat extends PostingsFormat {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return ramTerm.docs.size();
|
||||
}
|
||||
}
|
||||
|
||||
// Holds all indexes created, keyed by the ID assigned in fieldsConsumer
|
||||
|
|
|
@ -280,6 +280,11 @@ public abstract class BasePostingsFormatTestCase extends LuceneTestCase {
|
|||
}
|
||||
return docID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docFreq;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FieldAndTerm {
|
||||
|
|
|
@ -498,6 +498,11 @@ class SpatialDistanceQuery extends ExtendedQueryBase implements PostFilter {
|
|||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return maxDoc;
|
||||
}
|
||||
|
||||
public Explanation explain(int doc) throws IOException {
|
||||
advance(doc);
|
||||
boolean matched = this.doc == doc;
|
||||
|
|
|
@ -292,6 +292,17 @@ public class BitDocSet extends DocSetBase {
|
|||
pos = bs.nextSetBit(target+base);
|
||||
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
// we don't want to actually compute cardinality, but
|
||||
// if its already been computed, we use it
|
||||
if (size != -1) {
|
||||
return size;
|
||||
} else {
|
||||
return bs.capacity();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -186,6 +186,11 @@ abstract class DocSetBase implements DocSet {
|
|||
pos = bs.nextSetBit(target+base);
|
||||
return adjustedDoc = (pos>=0 && pos<max) ? pos-base : NO_MORE_DOCS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return bs.capacity();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -546,6 +546,11 @@ class JoinQuery extends Query {
|
|||
public int advance(int target) throws IOException {
|
||||
return iter.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return iter.cost();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -196,6 +196,11 @@ public class SolrConstantScoreQuery extends ConstantScoreQuery implements Extend
|
|||
public int advance(int target) throws IOException {
|
||||
return docIdSetIterator.advance(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docIdSetIterator.cost();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2307,6 +2307,11 @@ class FilterImpl extends Filter {
|
|||
public int advance(int target) throws IOException {
|
||||
return doNext(first.advance(target));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return first.cost();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DualFilterIterator extends DocIdSetIterator {
|
||||
|
@ -2344,6 +2349,11 @@ class FilterImpl extends Filter {
|
|||
if (other == doc) return doc;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return Math.min(a.cost(), b.cost());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -755,6 +755,10 @@ public class SortedIntDocSet extends DocSetBase {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cost() {
|
||||
return docs.length;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue