Skip to content

Commit

Permalink
QueryProfilerWeight to extend FilterWeight (#12242)
Browse files Browse the repository at this point in the history
QueryProfilerWeight should override matches and delegate to the
subQueryWeight. Another way to fix this issue is to make it extend
ProfileWeight and override only methods that need to have a different
behaviour than delegating to the sub weight.
  • Loading branch information
javanna committed Apr 26, 2023
1 parent 7e15a39 commit 615f456
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public Weight createWeight(Query query, ScoreMode scoreMode, float boost) throws
timer.stop();
profiler.pollLast();
}
return new QueryProfilerWeight(query, weight, profile);
return new QueryProfilerWeight(weight, profile);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
class QueryProfilerScorer extends Scorer {

private final Scorer scorer;
private QueryProfilerWeight profileWeight;
private final QueryProfilerWeight profileWeight;

private final QueryProfilerTimer scoreTimer,
nextDocTimer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import java.io.IOException;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.BulkScorer;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.FilterWeight;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.ScorerSupplier;
import org.apache.lucene.search.Weight;
Expand All @@ -30,14 +29,12 @@
* Weight wrapper that will compute how much time it takes to build the {@link Scorer} and then
* return a {@link Scorer} that is wrapped in order to compute timings as well.
*/
class QueryProfilerWeight extends Weight {
class QueryProfilerWeight extends FilterWeight {

private final Weight subQueryWeight;
private final QueryProfilerBreakdown profile;

public QueryProfilerWeight(Query query, Weight subQueryWeight, QueryProfilerBreakdown profile) {
super(query);
this.subQueryWeight = subQueryWeight;
public QueryProfilerWeight(Weight subQueryWeight, QueryProfilerBreakdown profile) {
super(subQueryWeight);
this.profile = profile;
}

Expand All @@ -46,7 +43,7 @@ public int count(LeafReaderContext context) throws IOException {
QueryProfilerTimer timer = profile.getTimer(QueryProfilerTimingType.COUNT);
timer.start();
try {
return subQueryWeight.count(context);
return in.count(context);
} finally {
timer.stop();
}
Expand All @@ -67,7 +64,7 @@ public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOExcepti
timer.start();
final ScorerSupplier subQueryScorerSupplier;
try {
subQueryScorerSupplier = subQueryWeight.scorerSupplier(context);
subQueryScorerSupplier = in.scorerSupplier(context);
} finally {
timer.stop();
}
Expand Down Expand Up @@ -103,7 +100,7 @@ public long cost() {
@Override
public BulkScorer bulkScorer(LeafReaderContext context) throws IOException {
// We use the default bulk scorer instead of the specialized one. The reason
// is that Lucene's BulkScorers do everything at once: finding matches,
// is that BulkScorers do everything at once: finding matches,
// scoring them and calling the collector, so they make it impossible to
// see where time is spent, which is the purpose of query profiling.
// The default bulk scorer will pull a scorer and iterate over matches,
Expand All @@ -112,11 +109,6 @@ public BulkScorer bulkScorer(LeafReaderContext context) throws IOException {
return super.bulkScorer(context);
}

@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
return subQueryWeight.explain(context, doc);
}

@Override
public boolean isCacheable(LeafReaderContext ctx) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void testPropagateMinCompetitiveScore() throws IOException {
query.createWeight(new IndexSearcher(new MultiReader()), ScoreMode.TOP_SCORES, 1f);
FakeScorer fakeScorer = new FakeScorer(weight);
QueryProfilerBreakdown profile = new QueryProfilerBreakdown();
QueryProfilerWeight queryProfilerWeight = new QueryProfilerWeight(query, weight, profile);
QueryProfilerWeight queryProfilerWeight = new QueryProfilerWeight(weight, profile);
QueryProfilerScorer queryProfilerScorer =
new QueryProfilerScorer(queryProfilerWeight, fakeScorer, profile);
queryProfilerScorer.setMinCompetitiveScore(0.42f);
Expand All @@ -83,7 +83,7 @@ public void testPropagateMaxScore() throws IOException {
query.createWeight(new IndexSearcher(new MultiReader()), ScoreMode.TOP_SCORES, 1f);
FakeScorer fakeScorer = new FakeScorer(weight);
QueryProfilerBreakdown profile = new QueryProfilerBreakdown();
QueryProfilerWeight queryProfilerWeight = new QueryProfilerWeight(query, weight, profile);
QueryProfilerWeight queryProfilerWeight = new QueryProfilerWeight(weight, profile);
QueryProfilerScorer queryProfilerScorer =
new QueryProfilerScorer(queryProfilerWeight, fakeScorer, profile);
queryProfilerScorer.setMinCompetitiveScore(0.42f);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* 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.
*/

package org.apache.lucene.sandbox.search;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Matches;
import org.apache.lucene.search.MatchesIterator;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import org.apache.lucene.tests.util.LuceneTestCase;

public class TestQueryProfilerWeight extends LuceneTestCase {

private static final class FakeWeight extends Weight {
FakeWeight(Query query) {
super(query);
}

@Override
public Explanation explain(LeafReaderContext context, int doc) {
return Explanation.match(1, "fake_description");
}

@Override
public Scorer scorer(LeafReaderContext context) {
return new Scorer(this) {
@Override
public DocIdSetIterator iterator() {
return null;
}

@Override
public float getMaxScore(int upTo) {
return 42f;
}

@Override
public float score() {
return 0;
}

@Override
public int docID() {
return 0;
}
};
}

@Override
public boolean isCacheable(LeafReaderContext ctx) {
return false;
}

@Override
public Matches matches(LeafReaderContext context, int doc) {
return new Matches() {
@Override
public MatchesIterator getMatches(String field) {
return new MatchesIterator() {
@Override
public boolean next() {
return false;
}

@Override
public int startPosition() {
return 42;
}

@Override
public int endPosition() {
return 43;
}

@Override
public int startOffset() {
return 44;
}

@Override
public int endOffset() {
return 45;
}

@Override
public MatchesIterator getSubMatches() {
return null;
}

@Override
public Query getQuery() {
return parentQuery;
}
};
}

@Override
public Collection<Matches> getSubMatches() {
return Collections.emptyList();
}

@Override
public Iterator<String> iterator() {
return null;
}
};
}
}

public void testPropagateMatches() throws IOException {
Query query = new MatchAllDocsQuery();
Weight fakeWeight = new FakeWeight(query);
QueryProfilerBreakdown profile = new QueryProfilerBreakdown();
QueryProfilerWeight profileWeight = new QueryProfilerWeight(fakeWeight, profile);
assertEquals(42, profileWeight.matches(null, 1).getMatches("some_field").startPosition());
}

public void testPropagateExplain() throws IOException {
Query query = new MatchAllDocsQuery();
Weight fakeWeight = new FakeWeight(query);
QueryProfilerBreakdown profile = new QueryProfilerBreakdown();
QueryProfilerWeight profileWeight = new QueryProfilerWeight(fakeWeight, profile);
assertEquals("fake_description", profileWeight.explain(null, 1).getDescription());
}

public void testPropagateScorer() throws IOException {
Query query = new MatchAllDocsQuery();
Weight fakeWeight = new FakeWeight(query);
QueryProfilerBreakdown profile = new QueryProfilerBreakdown();
QueryProfilerWeight profileWeight = new QueryProfilerWeight(fakeWeight, profile);
assertEquals(42f, profileWeight.scorer(null).getMaxScore(DocIdSetIterator.NO_MORE_DOCS), 0f);
}
}

0 comments on commit 615f456

Please sign in to comment.