Reduce branches in TopChildrenQuery

The branches used in the score method can be moved into the
scorer call and be essentially a constant operation rather than
a linear operation depending on the number of parent docs.
This commit is contained in:
Simon Willnauer 2013-05-13 11:11:30 +02:00
parent 52654179e7
commit a3a2ca0ad3
1 changed files with 45 additions and 34 deletions

View File

@ -320,7 +320,33 @@ public class TopChildrenQuery extends Query implements SearchContext.Rewrite {
public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder, boolean topScorer, Bits acceptDocs) throws IOException { public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder, boolean topScorer, Bits acceptDocs) throws IOException {
ParentDoc[] readerParentDocs = parentDocs.get(context.reader().getCoreCacheKey()); ParentDoc[] readerParentDocs = parentDocs.get(context.reader().getCoreCacheKey());
if (readerParentDocs != null) { if (readerParentDocs != null) {
return new ParentScorer(this, readerParentDocs); if (scoreType == ScoreType.MAX) {
return new ParentScorer(this, readerParentDocs) {
@Override
public float score() throws IOException {
assert doc.docId >= 0 || doc.docId < NO_MORE_DOCS;
return doc.maxScore;
}
};
} else if (scoreType == ScoreType.AVG) {
return new ParentScorer(this, readerParentDocs) {
@Override
public float score() throws IOException {
assert doc.docId >= 0 || doc.docId < NO_MORE_DOCS;
return doc.sumScores / doc.count;
}
};
} else if (scoreType == ScoreType.SUM) {
return new ParentScorer(this, readerParentDocs) {
@Override
public float score() throws IOException {
assert doc.docId >= 0 || doc.docId < NO_MORE_DOCS;
return doc.sumScores;
}
};
}
throw new ElasticSearchIllegalStateException("No support for score type [" + scoreType + "]");
} }
return new EmptyScorer(this); return new EmptyScorer(this);
} }
@ -331,31 +357,26 @@ public class TopChildrenQuery extends Query implements SearchContext.Rewrite {
} }
} }
class ParentScorer extends Scorer { static abstract class ParentScorer extends Scorer {
private final ParentDoc spare = new ParentDoc();
private final ParentDoc[] docs; protected final ParentDoc[] docs;
protected ParentDoc doc = spare;
private int index = -1; private int index = -1;
private ParentScorer(ParentWeight weight, ParentDoc[] docs) throws IOException { ParentScorer(ParentWeight weight, ParentDoc[] docs) throws IOException {
super(weight); super(weight);
this.docs = docs; this.docs = docs;
spare.docId = -1;
spare.count = -1;
} }
@Override @Override
public int docID() { public final int docID() {
if (index == -1) { return doc.docId;
return -1;
}
if (index >= docs.length) {
return NO_MORE_DOCS;
}
return docs[index].docId;
} }
@Override @Override
public int advance(int target) throws IOException { public final int advance(int target) throws IOException {
int doc; int doc;
while ((doc = nextDoc()) < target) { while ((doc = nextDoc()) < target) {
} }
@ -363,32 +384,22 @@ public class TopChildrenQuery extends Query implements SearchContext.Rewrite {
} }
@Override @Override
public int nextDoc() throws IOException { public final int nextDoc() throws IOException {
if (++index >= docs.length) { if (++index >= docs.length) {
return NO_MORE_DOCS; doc = spare;
doc.count = 0;
return (doc.docId = NO_MORE_DOCS);
} }
return docs[index].docId; return (doc = docs[index]).docId;
} }
@Override @Override
public float score() throws IOException { public final int freq() throws IOException {
if (scoreType == ScoreType.MAX) { return doc.count; // The number of matches in the child doc, which is propagated to parent
return docs[index].maxScore;
} else if (scoreType == ScoreType.AVG) {
return docs[index].sumScores / docs[index].count;
} else if (scoreType == ScoreType.SUM) {
return docs[index].sumScores;
}
throw new ElasticSearchIllegalStateException("No support for score type [" + scoreType + "]");
} }
@Override @Override
public int freq() throws IOException { public final long cost() {
return docs[index].count; // The number of matches in the child doc, which is propagated to parent
}
@Override
public long cost() {
return docs.length; return docs.length;
} }
} }