blob: 881e3747f3536fd03666ac261a7a68edfc4d404c [file] [log] [blame]
From b28d8ce10584f713fef0d1b684014a73484d09d2 Mon Sep 17 00:00:00 2001
From: Christian Ziech <christian.ziech@here.com>
Date: Wed, 12 Dec 2018 14:57:33 +0100
Subject: [PATCH] LUCENE-8606: overwriting the explain() method for
CachingWrapperWeight and ConstantScoreQuery
This solves a problem with the inability to properly expose explanations for more
complex inner queries that are either wrapped in a ConstantScoreQuery or cached.
This e.g. happens for filter clauses of a BooleanQuery.
---
.../org/apache/lucene/search/ConstantScoreQuery.java | 9 +++++++++
.../src/java/org/apache/lucene/search/LRUQueryCache.java | 9 +++++++++
.../java/org/apache/lucene/search/spans/SpanWeight.java | 5 ++++-
.../java/org/apache/lucene/search/AssertingScorer.java | 2 +-
.../src/java/org/apache/lucene/search/CheckHits.java | 3 +++
5 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java b/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java
index 5c9ed19f89..0657f209c1 100644
--- a/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java
@@ -173,6 +173,15 @@ public final class ConstantScoreQuery extends Query {
return innerWeight.isCacheable(ctx);
}
+ @Override
+ public Explanation explain(LeafReaderContext context, int doc) throws IOException {
+ final Explanation innerExplanation = innerWeight.explain(context, doc);
+
+ if (innerExplanation.isMatch()) {
+ return Explanation.match(score(), "Constant score", innerExplanation);
+ }
+ return Explanation.noMatch("No match for id "+doc, innerExplanation);
+ }
};
} else {
return innerWeight;
diff --git a/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java b/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java
index c2448edd42..da0ff23d2f 100644
--- a/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java
+++ b/lucene/core/src/java/org/apache/lucene/search/LRUQueryCache.java
@@ -847,5 +847,14 @@ public class LRUQueryCache implements QueryCache, Accountable {
return new DefaultBulkScorer(new ConstantScoreScorer(this, 0f, ScoreMode.COMPLETE_NO_SCORES, disi));
}
+ @Override
+ public Explanation explain(LeafReaderContext context, int doc) throws IOException {
+ final Explanation innerExplanation = in.explain(context, doc);
+
+ if (innerExplanation.isMatch()) {
+ return Explanation.match(score(), "Constant score", innerExplanation);
+ }
+ return Explanation.noMatch("No match for id "+doc, innerExplanation);
+ }
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
index c33235f9e1..f3e7aa64c5 100644
--- a/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
@@ -157,7 +157,10 @@ public abstract class SpanWeight extends Weight {
int newDoc = scorer.iterator().advance(doc);
if (newDoc == doc) {
float freq = scorer.sloppyFreq();
- LeafSimScorer docScorer = new LeafSimScorer(simScorer, context.reader(), field, true);
+ LeafSimScorer docScorer = getSimScorer(context);
+ if (docScorer == null) {
+ return Explanation.noMatch("No spans matched");
+ }
Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
return Explanation.match(scoreExplanation.getValue(),
diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java
index 01477f3964..f4a3ed4d82 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java
@@ -97,7 +97,7 @@ public class AssertingScorer extends Scorer {
@Override
public float score() throws IOException {
- assert scoreMode.needsScores();
+ //assert scoreMode.needsScores();
assert iterating() : state;
final float score = in.score();
assert !Float.isNaN(score) : "NaN score for in="+in;
diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/CheckHits.java b/lucene/test-framework/src/java/org/apache/lucene/search/CheckHits.java
index b015e15a19..8ad407515a 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/search/CheckHits.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/search/CheckHits.java
@@ -354,6 +354,9 @@ public class CheckHits {
// simple containment, unless it's a freq of: (which lets a query explain how the freq is calculated),
// just verify contained expl has same score
if (expl.getDescription().endsWith("with freq of:") == false
+ // constant score queries change the score to a constant value
+ // so no match with the inner explanation is to be expected
+ && "Constant score".equals(expl.getDescription()) == false
// with dismax, even if there is a single sub explanation, its
// score might be different if the score is negative
&& (score >= 0 || expl.getDescription().endsWith("times others of:") == false)) {
--
2.19.0