From c6821e1a1941e9ed6cbe35a3cb5be831bb6cfe1a Mon Sep 17 00:00:00 2001
From: Adrien Grand
Date: Tue, 21 Apr 2015 12:55:41 +0000
Subject: [PATCH] LUCENE-6446: Simplified Explanation API.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1675109 13f79535-47bb-0310-9956-ffa450edef68
---
lucene/CHANGES.txt | 2 +
.../apache/lucene/search/BooleanWeight.java | 63 ++++---------
.../lucene/search/ComplexExplanation.java | 71 --------------
.../lucene/search/ConstantScoreQuery.java | 14 +--
.../lucene/search/ConstantScoreWeight.java | 14 +--
.../lucene/search/DisjunctionMaxQuery.java | 18 ++--
.../org/apache/lucene/search/Explanation.java | 94 +++++++++++--------
.../java/org/apache/lucene/search/Filter.java | 6 +-
.../apache/lucene/search/FilteredQuery.java | 5 +-
.../lucene/search/MatchAllDocsQuery.java | 13 ++-
.../lucene/search/MultiPhraseQuery.java | 15 ++-
.../org/apache/lucene/search/PhraseQuery.java | 15 ++-
.../apache/lucene/search/QueryRescorer.java | 19 ++--
.../apache/lucene/search/SortRescorer.java | 16 ++--
.../org/apache/lucene/search/TermQuery.java | 18 ++--
.../search/payloads/PayloadFunction.java | 7 +-
.../search/payloads/PayloadNearQuery.java | 24 +++--
.../search/payloads/PayloadTermQuery.java | 32 +++----
.../search/similarities/AfterEffect.java | 2 +-
.../search/similarities/AfterEffectB.java | 13 ++-
.../search/similarities/AfterEffectL.java | 9 +-
.../search/similarities/BM25Similarity.java | 64 +++++++------
.../search/similarities/BasicModel.java | 14 +--
.../search/similarities/BasicModelIn.java | 14 +--
.../search/similarities/DFRSimilarity.java | 12 ++-
.../search/similarities/Distribution.java | 2 +-
.../search/similarities/IBSimilarity.java | 13 +--
.../similarities/LMDirichletSimilarity.java | 21 +++--
.../LMJelinekMercerSimilarity.java | 9 +-
.../search/similarities/LMSimilarity.java | 5 +-
.../lucene/search/similarities/LambdaDF.java | 13 +--
.../lucene/search/similarities/LambdaTTF.java | 13 +--
.../search/similarities/MultiSimilarity.java | 10 +-
.../search/similarities/Normalization.java | 16 ++--
.../search/similarities/Similarity.java | 9 +-
.../search/similarities/SimilarityBase.java | 26 ++---
.../search/similarities/TFIDFSimilarity.java | 89 ++++++++----------
.../lucene/search/spans/SpanWeight.java | 15 ++-
.../org/apache/lucene/index/TestOmitTf.java | 2 +-
.../lucene/search/TestDocValuesScoring.java | 9 +-
.../lucene/search/TestMultiPhraseQuery.java | 2 +-
.../lucene/search/TestQueryRescorer.java | 1 -
.../apache/lucene/search/TestSimilarity.java | 2 +-
.../lucene/search/TestSortRescorer.java | 2 +-
.../search/payloads/TestPayloadNearQuery.java | 2 +-
.../similarities/TestSimilarityBase.java | 2 +-
.../expressions/ExpressionRescorer.java | 9 +-
.../search/join/GlobalOrdinalsQuery.java | 11 +--
.../join/GlobalOrdinalsWithScoreQuery.java | 11 +--
.../search/join/TermsIncludingScoreQuery.java | 5 +-
.../search/join/ToParentBlockJoinQuery.java | 18 ++--
.../TestDiversifiedTopDocsCollector.java | 2 +-
.../lucene/queries/CustomScoreProvider.java | 18 ++--
.../lucene/queries/CustomScoreQuery.java | 11 +--
.../org/apache/lucene/queries/TermsQuery.java | 14 +--
.../lucene/queries/function/BoostedQuery.java | 13 +--
.../queries/function/FunctionQuery.java | 12 +--
.../queries/function/FunctionValues.java | 2 +-
.../lucene/queries/TestCustomScoreQuery.java | 43 ++++-----
.../bbox/BBoxOverlapRatioValueSource.java | 37 ++++----
.../bbox/BBoxSimilarityValueSource.java | 18 ++--
.../lucene/spatial/bbox/BBoxValueSource.java | 2 +-
.../serialized/SerializedDVStrategy.java | 2 +-
.../util/DistanceToShapeValueSource.java | 21 +++--
.../spatial/util/ShapeAreaValueSource.java | 9 +-
.../util/ShapePredicateValueSource.java | 9 +-
.../org/apache/lucene/search/CheckHits.java | 2 +-
.../org/apache/solr/schema/LatLonType.java | 25 ++---
.../apache/solr/search/JoinQParserPlugin.java | 18 +---
.../solr/search/SolrConstantScoreQuery.java | 18 +---
.../org/apache/solr/util/SolrPluginUtils.java | 2 +-
71 files changed, 496 insertions(+), 673 deletions(-)
delete mode 100644 lucene/core/src/java/org/apache/lucene/search/ComplexExplanation.java
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 52d2e63500d..10b8dd8b38a 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -123,6 +123,8 @@ API Changes
* LUCENE-6425: Replaced Query.extractTerms with Weight.extractTerms.
(Adrien Grand)
+* LUCENE-6446: Simplified Explanation API. (Adrien Grand)
+
Other
* LUCENE-6413: Test runner should report the number of suites completed/
diff --git a/lucene/core/src/java/org/apache/lucene/search/BooleanWeight.java b/lucene/core/src/java/org/apache/lucene/search/BooleanWeight.java
index ed81071e312..e89a5dcb759 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BooleanWeight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BooleanWeight.java
@@ -135,8 +135,7 @@ public class BooleanWeight extends Weight {
@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
final int minShouldMatch = query.getMinimumNumberShouldMatch();
- ComplexExplanation sumExpl = new ComplexExplanation();
- sumExpl.setDescription("sum of:");
+ List subs = new ArrayList<>();
int coord = 0;
float sum = 0.0f;
boolean fail = false;
@@ -146,30 +145,17 @@ public class BooleanWeight extends Weight {
for (Iterator wIter = weights.iterator(); wIter.hasNext();) {
Weight w = wIter.next();
BooleanClause c = cIter.next();
- if (w.scorer(context, context.reader().getLiveDocs()) == null) {
- if (c.isRequired()) {
- fail = true;
- Explanation r = new Explanation(0.0f, "no match on required clause (" + c.getQuery().toString() + ")");
- sumExpl.addDetail(r);
- }
- continue;
- }
Explanation e = w.explain(context, doc);
if (e.isMatch()) {
if (c.isScoring()) {
- sumExpl.addDetail(e);
+ subs.add(e);
sum += e.getValue();
coord++;
} else if (c.isRequired()) {
- Explanation r = new Explanation(0f, "match on required clause, product of:");
- r.addDetail(new Explanation(0f, Occur.FILTER + " clause"));
- r.addDetail(e);
- sumExpl.addDetail(r);
+ subs.add(Explanation.match(0f, "match on required clause, product of:",
+ Explanation.match(0f, Occur.FILTER + " clause"), e));
} else if (c.isProhibited()) {
- Explanation r =
- new Explanation(0.0f, "match on prohibited clause (" + c.getQuery().toString() + ")");
- r.addDetail(e);
- sumExpl.addDetail(r);
+ subs.add(Explanation.noMatch("match on prohibited clause (" + c.getQuery().toString() + ")", e));
fail = true;
}
if (!c.isProhibited()) {
@@ -179,39 +165,24 @@ public class BooleanWeight extends Weight {
shouldMatchCount++;
}
} else if (c.isRequired()) {
- Explanation r = new Explanation(0.0f, "no match on required clause (" + c.getQuery().toString() + ")");
- r.addDetail(e);
- sumExpl.addDetail(r);
+ subs.add(Explanation.noMatch("no match on required clause (" + c.getQuery().toString() + ")", e));
fail = true;
}
}
if (fail) {
- sumExpl.setMatch(Boolean.FALSE);
- sumExpl.setValue(0.0f);
- sumExpl.setDescription
- ("Failure to meet condition(s) of required/prohibited clause(s)");
- return sumExpl;
+ return Explanation.noMatch("Failure to meet condition(s) of required/prohibited clause(s)", subs);
+ } else if (matchCount == 0) {
+ return Explanation.noMatch("No matching clauses", subs);
} else if (shouldMatchCount < minShouldMatch) {
- sumExpl.setMatch(Boolean.FALSE);
- sumExpl.setValue(0.0f);
- sumExpl.setDescription("Failure to match minimum number "+
- "of optional clauses: " + minShouldMatch);
- return sumExpl;
- }
-
- sumExpl.setMatch(0 < matchCount);
- sumExpl.setValue(sum);
-
- final float coordFactor = disableCoord ? 1.0f : coord(coord, maxCoord);
- if (coordFactor == 1.0f) {
- return sumExpl; // eliminate wrapper
+ return Explanation.noMatch("Failure to match minimum number of optional clauses: " + minShouldMatch, subs);
} else {
- ComplexExplanation result = new ComplexExplanation(sumExpl.isMatch(),
- sum*coordFactor,
- "product of:");
- result.addDetail(sumExpl);
- result.addDetail(new Explanation(coordFactor,
- "coord("+coord+"/"+maxCoord+")"));
+ // we have a match
+ Explanation result = Explanation.match(sum, "sum of:", subs);
+ final float coordFactor = disableCoord ? 1.0f : coord(coord, maxCoord);
+ if (coordFactor != 1f) {
+ result = Explanation.match(sum * coordFactor, "product of:",
+ result, Explanation.match(coordFactor, "coord("+coord+"/"+maxCoord+")"));
+ }
return result;
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/ComplexExplanation.java b/lucene/core/src/java/org/apache/lucene/search/ComplexExplanation.java
deleted file mode 100644
index 511082cfee8..00000000000
--- a/lucene/core/src/java/org/apache/lucene/search/ComplexExplanation.java
+++ /dev/null
@@ -1,71 +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.
- */
-
-/** Expert: Describes the score computation for document and query, and
- * can distinguish a match independent of a positive value. */
-public class ComplexExplanation extends Explanation {
- private Boolean match;
-
- public ComplexExplanation() {
- super();
- }
-
- public ComplexExplanation(boolean match, float value, String description) {
- // NOTE: use of "boolean" instead of "Boolean" in params is conscious
- // choice to encourage clients to be specific.
- super(value, description);
- this.match = Boolean.valueOf(match);
- }
-
- /**
- * The match status of this explanation node.
- * @return May be null if match status is unknown
- */
- public Boolean getMatch() { return match; }
- /**
- * Sets the match status assigned to this explanation node.
- * @param match May be null if match status is unknown
- */
- public void setMatch(Boolean match) { this.match = match; }
- /**
- * Indicates whether or not this Explanation models a good match.
- *
- *
- * If the match status is explicitly set (i.e.: not null) this method
- * uses it; otherwise it defers to the superclass.
- *
- * @see #getMatch
- */
- @Override
- public boolean isMatch() {
- Boolean m = getMatch();
- return (null != m ? m.booleanValue() : super.isMatch());
- }
-
- @Override
- protected String getSummary() {
- if (null == getMatch())
- return super.getSummary();
-
- return getValue() + " = "
- + (isMatch() ? "(MATCH) " : "(NON-MATCH) ")
- + getDescription();
- }
-
-}
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 c5ba1f0d48e..c01cc9b06ca 100644
--- a/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/ConstantScoreQuery.java
@@ -117,19 +117,13 @@ public class ConstantScoreQuery extends Query {
final Scorer cs = scorer(context, context.reader().getLiveDocs());
final boolean exists = (cs != null && cs.advance(doc) == doc);
- final ComplexExplanation result = new ComplexExplanation();
if (exists) {
- result.setDescription(ConstantScoreQuery.this.toString() + ", product of:");
- result.setValue(queryWeight);
- result.setMatch(Boolean.TRUE);
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(queryNorm, "queryNorm"));
+ return Explanation.match(
+ queryWeight, ConstantScoreQuery.this.toString() + ", product of:",
+ Explanation.match(getBoost(), "boost"), Explanation.match(queryNorm, "queryNorm"));
} else {
- result.setDescription(ConstantScoreQuery.this.toString() + " doesn't match id " + doc);
- result.setValue(0);
- result.setMatch(Boolean.FALSE);
+ return Explanation.noMatch(ConstantScoreQuery.this.toString() + " doesn't match id " + doc);
}
- return result;
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/ConstantScoreWeight.java b/lucene/core/src/java/org/apache/lucene/search/ConstantScoreWeight.java
index 1b9ae13889f..b392aaba938 100644
--- a/lucene/core/src/java/org/apache/lucene/search/ConstantScoreWeight.java
+++ b/lucene/core/src/java/org/apache/lucene/search/ConstantScoreWeight.java
@@ -62,19 +62,13 @@ public abstract class ConstantScoreWeight extends Weight {
final Scorer s = scorer(context, context.reader().getLiveDocs());
final boolean exists = (s != null && s.advance(doc) == doc);
- final ComplexExplanation result = new ComplexExplanation();
if (exists) {
- result.setDescription(getQuery().toString() + ", product of:");
- result.setValue(queryWeight);
- result.setMatch(Boolean.TRUE);
- result.addDetail(new Explanation(getQuery().getBoost(), "boost"));
- result.addDetail(new Explanation(queryNorm, "queryNorm"));
+ return Explanation.match(
+ queryWeight, getQuery().toString() + ", product of:",
+ Explanation.match(getQuery().getBoost(), "boost"), Explanation.match(queryNorm, "queryNorm"));
} else {
- result.setDescription(getQuery().toString() + " doesn't match id " + doc);
- result.setValue(0);
- result.setMatch(Boolean.FALSE);
+ return Explanation.noMatch(getQuery().toString() + " doesn't match id " + doc);
}
- return result;
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java b/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java
index 83f66250253..5de3594bd05 100644
--- a/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java
@@ -184,21 +184,25 @@ public class DisjunctionMaxQuery extends Query implements Iterable {
/** Explain the score we computed for doc */
@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
- if (disjuncts.size() == 1) return weights.get(0).explain(context,doc);
- ComplexExplanation result = new ComplexExplanation();
+ boolean match = false;
float max = 0.0f, sum = 0.0f;
- result.setDescription(tieBreakerMultiplier == 0.0f ? "max of:" : "max plus " + tieBreakerMultiplier + " times others of:");
+ List subs = new ArrayList<>();
for (Weight wt : weights) {
Explanation e = wt.explain(context, doc);
if (e.isMatch()) {
- result.setMatch(Boolean.TRUE);
- result.addDetail(e);
+ match = true;
+ subs.add(e);
sum += e.getValue();
max = Math.max(max, e.getValue());
}
}
- result.setValue(max + (sum - max) * tieBreakerMultiplier);
- return result;
+ if (match) {
+ final float score = max + (sum - max) * tieBreakerMultiplier;
+ final String desc = tieBreakerMultiplier == 0.0f ? "max of:" : "max plus " + tieBreakerMultiplier + " times others of:";
+ return Explanation.match(score, desc, subs);
+ } else {
+ return Explanation.noMatch("No matching clause");
+ }
}
} // end of DisjunctionMaxWeight inner class
diff --git a/lucene/core/src/java/org/apache/lucene/search/Explanation.java b/lucene/core/src/java/org/apache/lucene/search/Explanation.java
index 5dad05ff601..cfeb6574c4a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/Explanation.java
+++ b/lucene/core/src/java/org/apache/lucene/search/Explanation.java
@@ -18,45 +18,74 @@ package org.apache.lucene.search;
*/
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
/** Expert: Describes the score computation for document and query. */
public class Explanation {
- private float value; // the value of this node
- private String description; // what it represents
- private ArrayList details; // sub-explanations
- public Explanation() {}
-
- public Explanation(float value, String description) {
- this.value = value;
- this.description = description;
+ /**
+ * Create a new explanation for a match.
+ * @param value the contribution to the score of the document
+ * @param description how {@code value} was computed
+ * @param details sub explanations that contributed to this explanation
+ */
+ public static Explanation match(float value, String description, Collection details) {
+ return new Explanation(true, value, description, details);
}
/**
- * Indicates whether or not this Explanation models a good match.
- *
- *
- * By default, an Explanation represents a "match" if the value is positive.
- *
- * @see #getValue
+ * Create a new explanation for a match.
+ * @param value the contribution to the score of the document
+ * @param description how {@code value} was computed
+ * @param details sub explanations that contributed to this explanation
*/
- public boolean isMatch() {
- return (0.0f < getValue());
+ public static Explanation match(float value, String description, Explanation... details) {
+ return new Explanation(true, value, description, Arrays.asList(details));
}
+ /**
+ * Create a new explanation for a document which does not match.
+ */
+ public static Explanation noMatch(String description, Collection details) {
+ return new Explanation(false, 0f, description, Collections.emptyList());
+ }
+ /**
+ * Create a new explanation for a document which does not match.
+ */
+ public static Explanation noMatch(String description, Explanation... details) {
+ return new Explanation(false, 0f, description, Collections.emptyList());
+ }
+
+ private final boolean match; // whether the document matched
+ private final float value; // the value of this node
+ private final String description; // what it represents
+ private final List details; // sub-explanations
+
+ /** Create a new explanation */
+ private Explanation(boolean match, float value, String description, Collection details) {
+ this.match = match;
+ this.value = value;
+ this.description = Objects.requireNonNull(description);
+ this.details = Collections.unmodifiableList(new ArrayList<>(details));
+ }
+
+ /**
+ * Indicates whether or not this Explanation models a match.
+ */
+ public boolean isMatch() {
+ return match;
+ }
/** The value assigned to this explanation node. */
public float getValue() { return value; }
- /** Sets the value assigned to this explanation node. */
- public void setValue(float value) { this.value = value; }
/** A description of this explanation node. */
public String getDescription() { return description; }
- /** Sets the description of this explanation node. */
- public void setDescription(String description) {
- this.description = description;
- }
/**
* A short one line summary which should contain all high level
@@ -68,18 +97,9 @@ public class Explanation {
/** The sub-nodes of this explanation node. */
public Explanation[] getDetails() {
- if (details == null)
- return null;
return details.toArray(new Explanation[0]);
}
- /** Adds a sub-node to this explanation node. */
- public void addDetail(Explanation detail) {
- if (details == null)
- details = new ArrayList<>();
- details.add(detail);
- }
-
/** Render an explanation as text. */
@Override
public String toString() {
@@ -94,10 +114,8 @@ public class Explanation {
buffer.append("\n");
Explanation[] details = getDetails();
- if (details != null) {
- for (int i = 0 ; i < details.length; i++) {
- buffer.append(details[i].toString(depth+1));
- }
+ for (int i = 0 ; i < details.length; i++) {
+ buffer.append(details[i].toString(depth+1));
}
return buffer.toString();
@@ -114,10 +132,8 @@ public class Explanation {
buffer.append("
\n");
Explanation[] details = getDetails();
- if (details != null) {
- for (int i = 0 ; i < details.length; i++) {
- buffer.append(details[i].toHtml());
- }
+ for (int i = 0 ; i < details.length; i++) {
+ buffer.append(details[i].toHtml());
}
buffer.append("\n");
diff --git a/lucene/core/src/java/org/apache/lucene/search/Filter.java b/lucene/core/src/java/org/apache/lucene/search/Filter.java
index ad37dfb6904..73f44358d83 100644
--- a/lucene/core/src/java/org/apache/lucene/search/Filter.java
+++ b/lucene/core/src/java/org/apache/lucene/search/Filter.java
@@ -95,14 +95,12 @@ public abstract class Filter extends Query {
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
final Scorer scorer = scorer(context, context.reader().getLiveDocs());
final boolean match = (scorer != null && scorer.advance(doc) == doc);
- final String desc;
if (match) {
assert scorer.score() == 0f;
- desc = "Match on id " + doc;
+ return Explanation.match(0f, "Match on id " + doc);
} else {
- desc = "No match on id " + doc;
+ return Explanation.match(0f, "No match on id " + doc);
}
- return new ComplexExplanation(match, 0f, desc);
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java b/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java
index c66f329aa47..3c5b8bac378 100644
--- a/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/FilteredQuery.java
@@ -108,10 +108,7 @@ public class FilteredQuery extends Query {
if (docIdSetIterator.advance(i) == i) {
return inner;
} else {
- Explanation result = new Explanation
- (0.0f, "failure to match filter: " + f.toString());
- result.addDetail(inner);
- return result;
+ return Explanation.noMatch("failure to match filter: " + f.toString(), inner);
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/MatchAllDocsQuery.java b/lucene/core/src/java/org/apache/lucene/search/MatchAllDocsQuery.java
index 7f13d2f98de..5517fcbc56d 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MatchAllDocsQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MatchAllDocsQuery.java
@@ -18,6 +18,8 @@ package org.apache.lucene.search;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
import org.apache.lucene.index.IndexReader;
@@ -119,15 +121,12 @@ public final class MatchAllDocsQuery extends Query {
@Override
public Explanation explain(LeafReaderContext context, int doc) {
- // explain query weight
- Explanation queryExpl = new ComplexExplanation
- (true, queryWeight, "MatchAllDocsQuery, product of:");
+ List subs = new ArrayList<>();
if (getBoost() != 1.0f) {
- queryExpl.addDetail(new Explanation(getBoost(),"boost"));
+ subs.add(Explanation.match(getBoost(),"boost"));
}
- queryExpl.addDetail(new Explanation(queryNorm,"queryNorm"));
-
- return queryExpl;
+ subs.add(Explanation.match(queryNorm, "queryNorm"));
+ return Explanation.match(queryWeight, "MatchAllDocsQuery, product of:", subs);
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
index 704320ab7a8..42d574a47b2 100644
--- a/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/MultiPhraseQuery.java
@@ -244,17 +244,16 @@ public class MultiPhraseQuery extends Query {
if (newDoc == doc) {
float freq = slop == 0 ? scorer.freq() : ((SloppyPhraseScorer)scorer).sloppyFreq();
SimScorer docScorer = similarity.simScorer(stats, context);
- ComplexExplanation result = new ComplexExplanation();
- result.setDescription("weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:");
- Explanation scoreExplanation = docScorer.explain(doc, new Explanation(freq, "phraseFreq=" + freq));
- result.addDetail(scoreExplanation);
- result.setValue(scoreExplanation.getValue());
- result.setMatch(true);
- return result;
+ Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
+ Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
+ return Explanation.match(
+ scoreExplanation.getValue(),
+ "weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:",
+ scoreExplanation);
}
}
- return new ComplexExplanation(false, 0.0f, "no matching term");
+ return Explanation.noMatch("no matching term");
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
index ff035adaa92..f5a6b875e88 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
@@ -341,17 +341,16 @@ public class PhraseQuery extends Query {
if (newDoc == doc) {
float freq = slop == 0 ? scorer.freq() : ((SloppyPhraseScorer)scorer).sloppyFreq();
SimScorer docScorer = similarity.simScorer(stats, context);
- ComplexExplanation result = new ComplexExplanation();
- result.setDescription("weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:");
- Explanation scoreExplanation = docScorer.explain(doc, new Explanation(freq, "phraseFreq=" + freq));
- result.addDetail(scoreExplanation);
- result.setValue(scoreExplanation.getValue());
- result.setMatch(true);
- return result;
+ Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
+ Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
+ return Explanation.match(
+ scoreExplanation.getValue(),
+ "weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:",
+ scoreExplanation);
}
}
- return new ComplexExplanation(false, 0.0f, "no matching term");
+ return Explanation.noMatch("no matching term");
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java
index b01668d9a86..141db7406ea 100644
--- a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java
@@ -17,14 +17,13 @@ package org.apache.lucene.search;
* limitations under the License.
*/
-import org.apache.lucene.index.PostingsEnum;
-import org.apache.lucene.index.LeafReaderContext;
-
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
+import org.apache.lucene.index.LeafReaderContext;
+
/** A {@link Rescorer} that uses a provided Query to assign
* scores to the first-pass hits.
*
@@ -151,22 +150,16 @@ public abstract class QueryRescorer extends Rescorer {
score = combine(firstPassExplanation.getValue(), true, secondPassScore.floatValue());
}
- Explanation result = new Explanation(score, "combined first and second pass score using " + getClass());
-
- Explanation first = new Explanation(firstPassExplanation.getValue(), "first pass score");
- first.addDetail(firstPassExplanation);
- result.addDetail(first);
+ Explanation first = Explanation.match(firstPassExplanation.getValue(), "first pass score", firstPassExplanation);
Explanation second;
if (secondPassScore == null) {
- second = new Explanation(0.0f, "no second pass score");
+ second = Explanation.noMatch("no second pass score");
} else {
- second = new Explanation(secondPassScore, "second pass score");
+ second = Explanation.match(secondPassScore, "second pass score", secondPassExplanation);
}
- second.addDetail(secondPassExplanation);
- result.addDetail(second);
- return result;
+ return Explanation.match(score, "combined first and second pass score using " + getClass(), first, second);
}
/** Sugar API, calling {#rescore} using a simple linear
diff --git a/lucene/core/src/java/org/apache/lucene/search/SortRescorer.java b/lucene/core/src/java/org/apache/lucene/search/SortRescorer.java
index af9cd67e202..2a0d27ef04e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/SortRescorer.java
+++ b/lucene/core/src/java/org/apache/lucene/search/SortRescorer.java
@@ -18,6 +18,7 @@ package org.apache.lucene.search;
*/
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -98,23 +99,22 @@ public class SortRescorer extends Rescorer {
TopDocs hits = rescore(searcher, oneHit, 1);
assert hits.totalHits == 1;
- // TODO: if we could ask the Sort to explain itself then
- // we wouldn't need the separate ExpressionRescorer...
- Explanation result = new Explanation(0.0f, "sort field values for sort=" + sort.toString());
+ List subs = new ArrayList<>();
// Add first pass:
- Explanation first = new Explanation(firstPassExplanation.getValue(), "first pass score");
- first.addDetail(firstPassExplanation);
- result.addDetail(first);
+ Explanation first = Explanation.match(firstPassExplanation.getValue(), "first pass score", firstPassExplanation);
+ subs.add(first);
FieldDoc fieldDoc = (FieldDoc) hits.scoreDocs[0];
// Add sort values:
SortField[] sortFields = sort.getSort();
for(int i=0;i details = new ArrayList<>();
for (final TermStatistics stat : termStats ) {
final long df = stat.docFreq();
final float termIdf = idf(df, max);
- exp.addDetail(new Explanation(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
+ details.add(Explanation.match(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
idf += termIdf;
}
- exp.setValue(idf);
- return exp;
+ return Explanation.match(idf, "idf(), sum of:", details);
}
@Override
@@ -292,34 +292,38 @@ public class BM25Similarity extends Similarity {
this.weight = idf.getValue() * queryBoost * topLevelBoost;
}
}
-
- private Explanation explainScore(int doc, Explanation freq, BM25Stats stats, NumericDocValues norms) {
- Explanation result = new Explanation();
- result.setDescription("score(doc="+doc+",freq="+freq+"), product of:");
-
- Explanation boostExpl = new Explanation(stats.queryBoost * stats.topLevelBoost, "boost");
- if (boostExpl.getValue() != 1.0f)
- result.addDetail(boostExpl);
-
- result.addDetail(stats.idf);
- Explanation tfNormExpl = new Explanation();
- tfNormExpl.setDescription("tfNorm, computed from:");
- tfNormExpl.addDetail(freq);
- tfNormExpl.addDetail(new Explanation(k1, "parameter k1"));
+ private Explanation explainTFNorm(int doc, Explanation freq, BM25Stats stats, NumericDocValues norms) {
+ List subs = new ArrayList<>();
+ subs.add(freq);
+ subs.add(Explanation.match(k1, "parameter k1"));
if (norms == null) {
- tfNormExpl.addDetail(new Explanation(0, "parameter b (norms omitted for field)"));
- tfNormExpl.setValue((freq.getValue() * (k1 + 1)) / (freq.getValue() + k1));
+ subs.add(Explanation.match(0, "parameter b (norms omitted for field)"));
+ return Explanation.match(
+ (freq.getValue() * (k1 + 1)) / (freq.getValue() + k1),
+ "parameter b (norms omitted for field)", subs);
} else {
float doclen = decodeNormValue((byte)norms.get(doc));
- tfNormExpl.addDetail(new Explanation(b, "parameter b"));
- tfNormExpl.addDetail(new Explanation(stats.avgdl, "avgFieldLength"));
- tfNormExpl.addDetail(new Explanation(doclen, "fieldLength"));
- tfNormExpl.setValue((freq.getValue() * (k1 + 1)) / (freq.getValue() + k1 * (1 - b + b * doclen/stats.avgdl)));
+ subs.add(Explanation.match(b, "parameter b"));
+ subs.add(Explanation.match(stats.avgdl, "avgFieldLength"));
+ subs.add(Explanation.match(doclen, "fieldLength"));
+ return Explanation.match(
+ (freq.getValue() * (k1 + 1)) / (freq.getValue() + k1 * (1 - b + b * doclen/stats.avgdl)),
+ "tfNorm, computed from:", subs);
}
- result.addDetail(tfNormExpl);
- result.setValue(boostExpl.getValue() * stats.idf.getValue() * tfNormExpl.getValue());
- return result;
+ }
+
+ private Explanation explainScore(int doc, Explanation freq, BM25Stats stats, NumericDocValues norms) {
+ Explanation boostExpl = Explanation.match(stats.queryBoost * stats.topLevelBoost, "boost");
+ List subs = new ArrayList<>();
+ if (boostExpl.getValue() != 1.0f)
+ subs.add(boostExpl);
+ subs.add(stats.idf);
+ Explanation tfNormExpl = explainTFNorm(doc, freq, stats, norms);
+ subs.add(tfNormExpl);
+ return Explanation.match(
+ boostExpl.getValue() * stats.idf.getValue() * tfNormExpl.getValue(),
+ "score(doc="+doc+",freq="+freq+"), product of:", subs);
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModel.java b/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModel.java
index 116fc2a871a..1c6b00748b6 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModel.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModel.java
@@ -47,15 +47,11 @@ public abstract class BasicModel {
* override this method.
*/
public Explanation explain(BasicStats stats, float tfn) {
- Explanation result = new Explanation();
- result.setDescription(getClass().getSimpleName() + ", computed from: ");
- result.setValue(score(stats, tfn));
- result.addDetail(new Explanation(tfn, "tfn"));
- result.addDetail(
- new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
- result.addDetail(
- new Explanation(stats.getTotalTermFreq(), "totalTermFreq"));
- return result;
+ return Explanation.match(
+ score(stats, tfn),
+ getClass().getSimpleName() + ", computed from: ",
+ Explanation.match(stats.getNumberOfDocuments(), "numberOfDocuments"),
+ Explanation.match(stats.getTotalTermFreq(), "totalTermFreq"));
}
/**
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModelIn.java b/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModelIn.java
index c52ad43d482..17c9a889a3e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModelIn.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/BasicModelIn.java
@@ -38,15 +38,11 @@ public class BasicModelIn extends BasicModel {
@Override
public final Explanation explain(BasicStats stats, float tfn) {
- Explanation result = new Explanation();
- result.setDescription(getClass().getSimpleName() + ", computed from: ");
- result.setValue(score(stats, tfn));
- result.addDetail(new Explanation(tfn, "tfn"));
- result.addDetail(
- new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
- result.addDetail(
- new Explanation(stats.getDocFreq(), "docFreq"));
- return result;
+ return Explanation.match(
+ score(stats, tfn),
+ getClass().getSimpleName() + ", computed from: ",
+ Explanation.match(stats.getNumberOfDocuments(), "numberOfDocuments"),
+ Explanation.match(stats.getDocFreq(), "docFreq"));
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
index 974a8f6fc67..64e5cd52612 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/DFRSimilarity.java
@@ -17,6 +17,8 @@ package org.apache.lucene.search.similarities;
* limitations under the License.
*/
+import java.util.List;
+
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.similarities.AfterEffect.NoAfterEffect;
import org.apache.lucene.search.similarities.Normalization.NoNormalization;
@@ -112,17 +114,17 @@ public class DFRSimilarity extends SimilarityBase {
}
@Override
- protected void explain(Explanation expl,
+ protected void explain(List subs,
BasicStats stats, int doc, float freq, float docLen) {
if (stats.getTotalBoost() != 1.0f) {
- expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+ subs.add(Explanation.match(stats.getTotalBoost(), "boost"));
}
Explanation normExpl = normalization.explain(stats, freq, docLen);
float tfn = normExpl.getValue();
- expl.addDetail(normExpl);
- expl.addDetail(basicModel.explain(stats, tfn));
- expl.addDetail(afterEffect.explain(stats, tfn));
+ subs.add(normExpl);
+ subs.add(basicModel.explain(stats, tfn));
+ subs.add(afterEffect.explain(stats, tfn));
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/Distribution.java b/lucene/core/src/java/org/apache/lucene/search/similarities/Distribution.java
index bbd07ea7a42..a171735b694 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/Distribution.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/Distribution.java
@@ -39,7 +39,7 @@ public abstract class Distribution {
/** Explains the score. Returns the name of the model only, since
* both {@code tfn} and {@code lambda} are explained elsewhere. */
public Explanation explain(BasicStats stats, float tfn, float lambda) {
- return new Explanation(
+ return Explanation.match(
score(stats, tfn, lambda), getClass().getSimpleName());
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
index fb7eae33335..81abcc5f4a5 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/IBSimilarity.java
@@ -17,6 +17,8 @@ package org.apache.lucene.search.similarities;
* limitations under the License.
*/
+import java.util.List;
+
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.similarities.Normalization.NoNormalization;
@@ -103,16 +105,15 @@ public class IBSimilarity extends SimilarityBase {
@Override
protected void explain(
- Explanation expl, BasicStats stats, int doc, float freq, float docLen) {
+ List subs, BasicStats stats, int doc, float freq, float docLen) {
if (stats.getTotalBoost() != 1.0f) {
- expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+ subs.add(Explanation.match(stats.getTotalBoost(), "boost"));
}
Explanation normExpl = normalization.explain(stats, freq, docLen);
Explanation lambdaExpl = lambda.explain(stats);
- expl.addDetail(normExpl);
- expl.addDetail(lambdaExpl);
- expl.addDetail(distribution.explain(
- stats, normExpl.getValue(), lambdaExpl.getValue()));
+ subs.add(normExpl);
+ subs.add(lambdaExpl);
+ subs.add(distribution.explain(stats, normExpl.getValue(), lambdaExpl.getValue()));
}
/**
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
index 9cc4b62795d..7b91191c04e 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LMDirichletSimilarity.java
@@ -17,6 +17,7 @@ package org.apache.lucene.search.similarities;
* limitations under the License.
*/
+import java.util.List;
import java.util.Locale;
import org.apache.lucene.search.Explanation;
@@ -70,21 +71,21 @@ public class LMDirichletSimilarity extends LMSimilarity {
}
@Override
- protected void explain(Explanation expl, BasicStats stats, int doc,
+ protected void explain(List subs, BasicStats stats, int doc,
float freq, float docLen) {
if (stats.getTotalBoost() != 1.0f) {
- expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+ subs.add(Explanation.match(stats.getTotalBoost(), "boost"));
}
- expl.addDetail(new Explanation(mu, "mu"));
- Explanation weightExpl = new Explanation();
- weightExpl.setValue((float)Math.log(1 + freq /
- (mu * ((LMStats)stats).getCollectionProbability())));
- weightExpl.setDescription("term weight");
- expl.addDetail(weightExpl);
- expl.addDetail(new Explanation(
+ subs.add(Explanation.match(mu, "mu"));
+ Explanation weightExpl = Explanation.match(
+ (float)Math.log(1 + freq /
+ (mu * ((LMStats)stats).getCollectionProbability())),
+ "term weight");
+ subs.add(weightExpl);
+ subs.add(Explanation.match(
(float)Math.log(mu / (docLen + mu)), "document norm"));
- super.explain(expl, stats, doc, freq, docLen);
+ super.explain(subs, stats, doc, freq, docLen);
}
/** Returns the μ parameter. */
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
index 36f4b9c83b0..e0e2420a665 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LMJelinekMercerSimilarity.java
@@ -17,6 +17,7 @@ package org.apache.lucene.search.similarities;
* limitations under the License.
*/
+import java.util.List;
import java.util.Locale;
import org.apache.lucene.search.Explanation;
@@ -58,13 +59,13 @@ public class LMJelinekMercerSimilarity extends LMSimilarity {
}
@Override
- protected void explain(Explanation expl, BasicStats stats, int doc,
+ protected void explain(List subs, BasicStats stats, int doc,
float freq, float docLen) {
if (stats.getTotalBoost() != 1.0f) {
- expl.addDetail(new Explanation(stats.getTotalBoost(), "boost"));
+ subs.add(Explanation.match(stats.getTotalBoost(), "boost"));
}
- expl.addDetail(new Explanation(lambda, "lambda"));
- super.explain(expl, stats, doc, freq, docLen);
+ subs.add(Explanation.match(lambda, "lambda"));
+ super.explain(subs, stats, doc, freq, docLen);
}
/** Returns the λ parameter. */
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LMSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LMSimilarity.java
index 047673657d1..a29eb7229ba 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LMSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LMSimilarity.java
@@ -17,6 +17,7 @@ package org.apache.lucene.search.similarities;
* limitations under the License.
*/
+import java.util.List;
import java.util.Locale;
import org.apache.lucene.search.CollectionStatistics;
@@ -69,9 +70,9 @@ public abstract class LMSimilarity extends SimilarityBase {
}
@Override
- protected void explain(Explanation expl, BasicStats stats, int doc,
+ protected void explain(List subExpls, BasicStats stats, int doc,
float freq, float docLen) {
- expl.addDetail(new Explanation(collectionModel.computeProbability(stats),
+ subExpls.add(Explanation.match(collectionModel.computeProbability(stats),
"collection probability"));
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaDF.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaDF.java
index 58ac3533232..c34cfc62493 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaDF.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaDF.java
@@ -35,14 +35,11 @@ public class LambdaDF extends Lambda {
@Override
public final Explanation explain(BasicStats stats) {
- Explanation result = new Explanation();
- result.setDescription(getClass().getSimpleName() + ", computed from: ");
- result.setValue(lambda(stats));
- result.addDetail(
- new Explanation(stats.getDocFreq(), "docFreq"));
- result.addDetail(
- new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
- return result;
+ return Explanation.match(
+ lambda(stats),
+ getClass().getSimpleName() + ", computed from: ",
+ Explanation.match(stats.getDocFreq(), "docFreq"),
+ Explanation.match(stats.getNumberOfDocuments(), "numberOfDocuments"));
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaTTF.java b/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaTTF.java
index a9a856ecc2f..c5ffb50cc2a 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaTTF.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/LambdaTTF.java
@@ -35,14 +35,11 @@ public class LambdaTTF extends Lambda {
@Override
public final Explanation explain(BasicStats stats) {
- Explanation result = new Explanation();
- result.setDescription(getClass().getSimpleName() + ", computed from: ");
- result.setValue(lambda(stats));
- result.addDetail(
- new Explanation(stats.getTotalTermFreq(), "totalTermFreq"));
- result.addDetail(
- new Explanation(stats.getNumberOfDocuments(), "numberOfDocuments"));
- return result;
+ return Explanation.match(
+ lambda(stats),
+ getClass().getSimpleName() + ", computed from: ",
+ Explanation.match(stats.getTotalTermFreq(), "totalTermFreq"),
+ Explanation.match(stats.getNumberOfDocuments(), "numberOfDocuments"));
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
index 1870282ce05..aceeeca9d09 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/MultiSimilarity.java
@@ -18,9 +18,11 @@ package org.apache.lucene.search.similarities;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.CollectionStatistics;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.TermStatistics;
@@ -83,11 +85,11 @@ public class MultiSimilarity extends Similarity {
@Override
public Explanation explain(int doc, Explanation freq) {
- Explanation expl = new Explanation(score(doc, freq.getValue()), "sum of:");
+ List subs = new ArrayList<>();
for (SimScorer subScorer : subScorers) {
- expl.addDetail(subScorer.explain(doc, freq));
+ subs.add(subScorer.explain(doc, freq));
}
- return expl;
+ return Explanation.match(score(doc, freq.getValue()), "sum of:", subs);
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/Normalization.java b/lucene/core/src/java/org/apache/lucene/search/similarities/Normalization.java
index e27159f6d75..786726f81a4 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/Normalization.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/Normalization.java
@@ -45,14 +45,12 @@ public abstract class Normalization {
* Subclasses that use other statistics must override this method.
*/
public Explanation explain(BasicStats stats, float tf, float len) {
- Explanation result = new Explanation();
- result.setDescription(getClass().getSimpleName() + ", computed from: ");
- result.setValue(tfn(stats, tf, len));
- result.addDetail(new Explanation(tf, "tf"));
- result.addDetail(
- new Explanation(stats.getAvgFieldLength(), "avgFieldLength"));
- result.addDetail(new Explanation(len, "len"));
- return result;
+ return Explanation.match(
+ tfn(stats, tf, len),
+ getClass().getSimpleName() + ", computed from: ",
+ Explanation.match(tf, "tf"),
+ Explanation.match(stats.getAvgFieldLength(), "avgFieldLength"),
+ Explanation.match(len, "len"));
}
/** Implementation used when there is no normalization. */
@@ -68,7 +66,7 @@ public abstract class Normalization {
@Override
public final Explanation explain(BasicStats stats, float tf, float len) {
- return new Explanation(1, "no normalization");
+ return Explanation.match(1, "no normalization");
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
index 65f05299ec7..4acebe9dc08 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
@@ -31,6 +31,7 @@ import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.SmallFloat;
import java.io.IOException;
+import java.util.Collections;
/**
* Similarity defines the components of Lucene scoring.
@@ -210,10 +211,10 @@ public abstract class Similarity {
* @return document's score
*/
public Explanation explain(int doc, Explanation freq) {
- Explanation result = new Explanation(score(doc, freq.getValue()),
- "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:");
- result.addDetail(freq);
- return result;
+ return Explanation.match(
+ score(doc, freq.getValue()),
+ "score(doc=" + doc + ",freq=" + freq.getValue() +"), with freq of:",
+ Collections.singleton(freq));
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java b/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
index 37f63e2f766..db1cabf0442 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/SimilarityBase.java
@@ -18,9 +18,11 @@ package org.apache.lucene.search.similarities;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.search.CollectionStatistics;
import org.apache.lucene.search.Explanation;
@@ -32,7 +34,7 @@ import org.apache.lucene.util.SmallFloat;
* A subclass of {@code Similarity} that provides a simplified API for its
* descendants. Subclasses are only required to implement the {@link #score}
* and {@link #toString()} methods. Implementing
- * {@link #explain(Explanation, BasicStats, int, float, float)} is optional,
+ * {@link #explain(List, BasicStats, int, float, float)} is optional,
* inasmuch as SimilarityBase already provides a basic explanation of the score
* and the term frequency. However, implementers of a subclass are encouraged to
* include as much detail about the scoring method as possible.
@@ -152,14 +154,14 @@ public abstract class SimilarityBase extends Similarity {
* clauses to explain details of their scoring formulae.
* The default implementation does nothing.
*
- * @param expl the explanation to extend with details.
+ * @param subExpls the list of details of the explanation to extend
* @param stats the corpus level statistics.
* @param doc the document id.
* @param freq the term frequency.
* @param docLen the document length.
*/
protected void explain(
- Explanation expl, BasicStats stats, int doc, float freq, float docLen) {}
+ List subExpls, BasicStats stats, int doc, float freq, float docLen) {}
/**
* Explains the score. The implementation here provides a basic explanation
@@ -168,7 +170,7 @@ public abstract class SimilarityBase extends Similarity {
* attaches the score (computed via the {@link #score(BasicStats, float, float)}
* method) and the explanation for the term frequency. Subclasses content with
* this format may add additional details in
- * {@link #explain(Explanation, BasicStats, int, float, float)}.
+ * {@link #explain(List, BasicStats, int, float, float)}.
*
* @param stats the corpus level statistics.
* @param doc the document id.
@@ -178,15 +180,13 @@ public abstract class SimilarityBase extends Similarity {
*/
protected Explanation explain(
BasicStats stats, int doc, Explanation freq, float docLen) {
- Explanation result = new Explanation();
- result.setValue(score(stats, freq.getValue(), docLen));
- result.setDescription("score(" + getClass().getSimpleName() +
- ", doc=" + doc + ", freq=" + freq.getValue() +"), computed from:");
- result.addDetail(freq);
+ List subs = new ArrayList<>();
+ explain(subs, stats, doc, freq.getValue(), docLen);
- explain(result, stats, doc, freq.getValue(), docLen);
-
- return result;
+ return Explanation.match(
+ score(stats, freq.getValue(), docLen),
+ "score(" + getClass().getSimpleName() + ", doc=" + doc + ", freq=" + freq.getValue() +"), computed from:",
+ subs);
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java b/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
index 63cd8be446f..dcfcd82036f 100644
--- a/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
+++ b/lucene/core/src/java/org/apache/lucene/search/similarities/TFIDFSimilarity.java
@@ -18,9 +18,11 @@ package org.apache.lucene.search.similarities;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.search.CollectionStatistics;
import org.apache.lucene.search.Explanation;
@@ -582,7 +584,7 @@ public abstract class TFIDFSimilarity extends Similarity {
final long df = termStats.docFreq();
final long max = collectionStats.maxDoc();
final float idf = idf(df, max);
- return new Explanation(idf, "idf(docFreq=" + df + ", maxDocs=" + max + ")");
+ return Explanation.match(idf, "idf(docFreq=" + df + ", maxDocs=" + max + ")");
}
/**
@@ -601,16 +603,14 @@ public abstract class TFIDFSimilarity extends Similarity {
public Explanation idfExplain(CollectionStatistics collectionStats, TermStatistics termStats[]) {
final long max = collectionStats.maxDoc();
float idf = 0.0f;
- final Explanation exp = new Explanation();
- exp.setDescription("idf(), sum of:");
+ List subs = new ArrayList<>();
for (final TermStatistics stat : termStats ) {
final long df = stat.docFreq();
final float termIdf = idf(df, max);
- exp.addDetail(new Explanation(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
+ subs.add(Explanation.match(termIdf, "idf(docFreq=" + df + ", maxDocs=" + max + ")"));
idf += termIdf;
}
- exp.setValue(idf);
- return exp;
+ return Explanation.match(idf, "idf(), sum of:", subs);
}
/** Computes a score factor based on a term's document frequency (the number
@@ -764,58 +764,43 @@ public abstract class TFIDFSimilarity extends Similarity {
}
}
- private Explanation explainScore(int doc, Explanation freq, IDFStats stats, NumericDocValues norms) {
- Explanation result = new Explanation();
- result.setDescription("score(doc="+doc+",freq="+freq.getValue()+"), product of:");
+ private Explanation explainQuery(IDFStats stats) {
+ List subs = new ArrayList<>();
- // explain query weight
- Explanation queryExpl = new Explanation();
- queryExpl.setDescription("queryWeight, product of:");
-
- Explanation boostExpl = new Explanation(stats.queryBoost, "boost");
+ Explanation boostExpl = Explanation.match(stats.queryBoost, "boost");
if (stats.queryBoost != 1.0f)
- queryExpl.addDetail(boostExpl);
- queryExpl.addDetail(stats.idf);
+ subs.add(boostExpl);
+ subs.add(stats.idf);
- Explanation queryNormExpl = new Explanation(stats.queryNorm,"queryNorm");
- queryExpl.addDetail(queryNormExpl);
+ Explanation queryNormExpl = Explanation.match(stats.queryNorm,"queryNorm");
+ subs.add(queryNormExpl);
- queryExpl.setValue(boostExpl.getValue() *
- stats.idf.getValue() *
- queryNormExpl.getValue());
+ return Explanation.match(
+ boostExpl.getValue() * stats.idf.getValue() * queryNormExpl.getValue(),
+ "queryWeight, product of:", subs);
+ }
- result.addDetail(queryExpl);
+ private Explanation explainField(int doc, Explanation freq, IDFStats stats, NumericDocValues norms) {
+ Explanation tfExplanation = Explanation.match(tf(freq.getValue()), "tf(freq="+freq.getValue()+"), with freq of:", freq);
+ Explanation fieldNormExpl = Explanation.match(
+ norms != null ? decodeNormValue(norms.get(doc)) : 1.0f,
+ "fieldNorm(doc=" + doc + ")");
- // explain field weight
- Explanation fieldExpl = new Explanation();
- fieldExpl.setDescription("fieldWeight in "+doc+
- ", product of:");
+ return Explanation.match(
+ tfExplanation.getValue() * stats.idf.getValue() * fieldNormExpl.getValue(),
+ "fieldWeight in " + doc + ", product of:",
+ tfExplanation, stats.idf, fieldNormExpl);
+ }
- Explanation tfExplanation = new Explanation();
- tfExplanation.setValue(tf(freq.getValue()));
- tfExplanation.setDescription("tf(freq="+freq.getValue()+"), with freq of:");
- tfExplanation.addDetail(freq);
- fieldExpl.addDetail(tfExplanation);
- fieldExpl.addDetail(stats.idf);
-
- Explanation fieldNormExpl = new Explanation();
- float fieldNorm = norms != null ? decodeNormValue(norms.get(doc)) : 1.0f;
- fieldNormExpl.setValue(fieldNorm);
- fieldNormExpl.setDescription("fieldNorm(doc="+doc+")");
- fieldExpl.addDetail(fieldNormExpl);
-
- fieldExpl.setValue(tfExplanation.getValue() *
- stats.idf.getValue() *
- fieldNormExpl.getValue());
-
- result.addDetail(fieldExpl);
-
- // combine them
- result.setValue(queryExpl.getValue() * fieldExpl.getValue());
-
- if (queryExpl.getValue() == 1.0f)
+ private Explanation explainScore(int doc, Explanation freq, IDFStats stats, NumericDocValues norms) {
+ Explanation queryExpl = explainQuery(stats);
+ Explanation fieldExpl = explainField(doc, freq, stats, norms);
+ if (queryExpl.getValue() == 1f) {
return fieldExpl;
-
- return result;
+ }
+ return Explanation.match(
+ queryExpl.getValue() * fieldExpl.getValue(),
+ "score(doc="+doc+",freq="+freq.getValue()+"), product of:",
+ queryExpl, fieldExpl);
}
}
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 e375b31a0c7..260bfbde75b 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
@@ -28,7 +28,6 @@ import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.index.Terms;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Scorer;
@@ -110,16 +109,14 @@ public class SpanWeight extends Weight {
if (newDoc == doc) {
float freq = scorer.sloppyFreq();
SimScorer docScorer = similarity.simScorer(stats, context);
- ComplexExplanation result = new ComplexExplanation();
- result.setDescription("weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:");
- Explanation scoreExplanation = docScorer.explain(doc, new Explanation(freq, "phraseFreq=" + freq));
- result.addDetail(scoreExplanation);
- result.setValue(scoreExplanation.getValue());
- result.setMatch(true);
- return result;
+ Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
+ Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
+ return Explanation.match(scoreExplanation.getValue(),
+ "weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:",
+ scoreExplanation);
}
}
- return new ComplexExplanation(false, 0.0f, "no matching term");
+ return Explanation.noMatch("no matching term");
}
}
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java b/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
index 2a7e120d3c5..3e61c80808a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestOmitTf.java
@@ -56,7 +56,7 @@ public class TestOmitTf extends LuceneTestCase {
@Override public float sloppyFreq(int distance) { return 2.0f; }
@Override public float idf(long docFreq, long numDocs) { return 1.0f; }
@Override public Explanation idfExplain(CollectionStatistics collectionStats, TermStatistics[] termStats) {
- return new Explanation(1.0f, "Inexplicable");
+ return Explanation.match(1.0f, "Inexplicable");
}
@Override public float scorePayload(int doc, int start, int end, BytesRef payload) { return 1.0f; }
}
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
index 89821c5ff82..75992866371 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesScoring.java
@@ -180,12 +180,11 @@ public class TestDocValuesScoring extends LuceneTestCase {
@Override
public Explanation explain(int doc, Explanation freq) {
- Explanation boostExplanation = new Explanation(Float.intBitsToFloat((int)values.get(doc)), "indexDocValue(" + boostField + ")");
+ Explanation boostExplanation = Explanation.match(Float.intBitsToFloat((int)values.get(doc)), "indexDocValue(" + boostField + ")");
Explanation simExplanation = sub.explain(doc, freq);
- Explanation expl = new Explanation(boostExplanation.getValue() * simExplanation.getValue(), "product of:");
- expl.addDetail(boostExplanation);
- expl.addDetail(simExplanation);
- return expl;
+ return Explanation.match(
+ boostExplanation.getValue() * simExplanation.getValue(),
+ "product of:", boostExplanation, simExplanation);
}
};
}
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
index e62bda57fae..980262b6467 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
@@ -337,7 +337,7 @@ public class TestMultiPhraseQuery extends LuceneTestCase {
searcher.setSimilarity(new DefaultSimilarity() {
@Override
public Explanation idfExplain(CollectionStatistics collectionStats, TermStatistics termStats[]) {
- return new Explanation(10f, "just a test");
+ return Explanation.match(10f, "just a test");
}
});
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
index 1245a96fa40..0e4c85675f6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestQueryRescorer.java
@@ -272,7 +272,6 @@ public class TestQueryRescorer extends LuceneTestCase {
assertTrue(s.contains("first pass score"));
assertTrue(s.contains("no second pass score"));
assertFalse(s.contains("= second pass score"));
- assertTrue(s.contains("NON-MATCH"));
assertEquals(hits2.scoreDocs[1].score, explain.getValue(), 0.0f);
r.close();
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java b/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
index 43b58aa727a..5d85da11935 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSimilarity.java
@@ -48,7 +48,7 @@ public class TestSimilarity extends LuceneTestCase {
@Override public float sloppyFreq(int distance) { return 2.0f; }
@Override public float idf(long docFreq, long numDocs) { return 1.0f; }
@Override public Explanation idfExplain(CollectionStatistics collectionStats, TermStatistics[] stats) {
- return new Explanation(1.0f, "Inexplicable");
+ return Explanation.match(1.0f, "Inexplicable");
}
}
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSortRescorer.java b/lucene/core/src/test/org/apache/lucene/search/TestSortRescorer.java
index 033b37fe6bb..0c159584fbb 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSortRescorer.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSortRescorer.java
@@ -101,7 +101,7 @@ public class TestSortRescorer extends LuceneTestCase {
// Confirm the explanation breaks out the individual
// sort fields:
- assertTrue(expl.contains("= sort field ! value=20"));
+ assertTrue(expl, expl.contains("= sort field ! value=20"));
// Confirm the explanation includes first pass details:
assertTrue(expl.contains("= first pass score"));
diff --git a/lucene/core/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java b/lucene/core/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java
index fe977a67ca1..9bde81a4999 100644
--- a/lucene/core/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java
@@ -341,7 +341,7 @@ public class TestPayloadNearQuery extends LuceneTestCase {
// idf used for phrase queries
@Override
public Explanation idfExplain(CollectionStatistics collectionStats, TermStatistics[] termStats) {
- return new Explanation(1.0f, "Inexplicable");
+ return Explanation.match(1.0f, "Inexplicable");
}
}
}
diff --git a/lucene/core/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java b/lucene/core/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java
index f1ae67be2c7..cf61cb60b95 100644
--- a/lucene/core/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java
+++ b/lucene/core/src/test/org/apache/lucene/search/similarities/TestSimilarityBase.java
@@ -194,7 +194,7 @@ public class TestSimilarityBase extends LuceneTestCase {
toTermStats(stats));
float score = sim.score(realStats, freq, docLen);
float explScore = sim.explain(
- realStats, 1, new Explanation(freq, "freq"), docLen).getValue();
+ realStats, 1, Explanation.match(freq, "freq"), docLen).getValue();
assertFalse("Score infinite: " + sim.toString(), Float.isInfinite(score));
assertFalse("Score NaN: " + sim.toString(), Float.isNaN(score));
assertTrue("Score negative: " + sim.toString(), score >= 0);
diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
index 884dea73b05..79812a0954a 100644
--- a/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
+++ b/lucene/expressions/src/java/org/apache/lucene/expressions/ExpressionRescorer.java
@@ -18,6 +18,8 @@ package org.apache.lucene.expressions;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -57,7 +59,7 @@ class ExpressionRescorer extends SortRescorer {
@Override
public Explanation explain(IndexSearcher searcher, Explanation firstPassExplanation, int docID) throws IOException {
- Explanation result = super.explain(searcher, firstPassExplanation, docID);
+ Explanation superExpl = super.explain(searcher, firstPassExplanation, docID);
List leaves = searcher.getIndexReader().leaves();
int subReader = ReaderUtil.subIndex(docID, leaves);
@@ -71,11 +73,12 @@ class ExpressionRescorer extends SortRescorer {
context.put("scorer", fakeScorer);
+ List subs = new ArrayList<>(Arrays.asList(superExpl.getDetails()));
for(String variable : expression.variables) {
- result.addDetail(new Explanation((float) bindings.getValueSource(variable).getValues(context, readerContext).doubleVal(docIDInSegment),
+ subs.add(Explanation.match((float) bindings.getValueSource(variable).getValues(context, readerContext).doubleVal(docIDInSegment),
"variable \"" + variable + "\""));
}
- return result;
+ return Explanation.match(superExpl.getValue(), superExpl.getDescription(), subs);
}
}
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
index b901bbd0a2f..f292f53e9b4 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsQuery.java
@@ -17,13 +17,15 @@ package org.apache.lucene.search.join;
* limitations under the License.
*/
+import java.io.IOException;
+import java.util.Set;
+
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@@ -36,9 +38,6 @@ import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.LongBitSet;
import org.apache.lucene.util.LongValues;
-import java.io.IOException;
-import java.util.Set;
-
final class GlobalOrdinalsQuery extends Query {
// All the ords of matching docs found with OrdinalsCollector.
@@ -121,10 +120,10 @@ final class GlobalOrdinalsQuery extends Query {
int segmentOrd = values.getOrd(doc);
if (segmentOrd != -1) {
BytesRef joinValue = values.lookupOrd(segmentOrd);
- return new ComplexExplanation(true, queryNorm, "Score based on join value " + joinValue.utf8ToString());
+ return Explanation.match(queryNorm, "Score based on join value " + joinValue.utf8ToString());
}
}
- return new ComplexExplanation(false, 0.0f, "Not a match");
+ return Explanation.noMatch("Not a match");
}
@Override
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
index 146a0dacba3..093475b8f53 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/GlobalOrdinalsWithScoreQuery.java
@@ -17,13 +17,15 @@ package org.apache.lucene.search.join;
* limitations under the License.
*/
+import java.io.IOException;
+import java.util.Set;
+
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@@ -35,9 +37,6 @@ import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.LongValues;
-import java.io.IOException;
-import java.util.Set;
-
final class GlobalOrdinalsWithScoreQuery extends Query {
private final GlobalOrdinalsWithScoreCollector collector;
@@ -126,10 +125,10 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
score = collector.score(segmentOrd);
}
BytesRef joinValue = values.lookupOrd(segmentOrd);
- return new ComplexExplanation(true, score, "Score based on join value " + joinValue.utf8ToString());
+ return Explanation.match(score, "Score based on join value " + joinValue.utf8ToString());
}
}
- return new ComplexExplanation(false, 0.0f, "Not a match");
+ return Explanation.noMatch("Not a match");
}
@Override
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java
index 3e92f728a79..d44b9edb64e 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/TermsIncludingScoreQuery.java
@@ -27,7 +27,6 @@ import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@@ -137,12 +136,12 @@ class TermsIncludingScoreQuery extends Query {
postingsEnum = segmentTermsEnum.postings(null, postingsEnum, PostingsEnum.NONE);
if (postingsEnum.advance(doc) == doc) {
final float score = TermsIncludingScoreQuery.this.scores[ords[i]];
- return new ComplexExplanation(true, score, "Score based on join value " + segmentTermsEnum.term().utf8ToString());
+ return Explanation.match(score, "Score based on join value " + segmentTermsEnum.term().utf8ToString());
}
}
}
}
- return new ComplexExplanation(false, 0.0f, "Not a match");
+ return Explanation.noMatch("Not a match");
}
@Override
diff --git a/lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinQuery.java b/lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinQuery.java
index fb08ee2e1f6..3013d2f4087 100644
--- a/lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinQuery.java
+++ b/lucene/join/src/java/org/apache/lucene/search/join/ToParentBlockJoinQuery.java
@@ -17,11 +17,16 @@ package org.apache.lucene.search.join;
* limitations under the License.
*/
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+import java.util.Set;
+
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@@ -34,12 +39,6 @@ import org.apache.lucene.util.BitDocIdSet;
import org.apache.lucene.util.BitSet;
import org.apache.lucene.util.Bits;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Locale;
-import java.util.Set;
-
/**
* This query requires that you index
* children and parent docs as a single block, using the
@@ -190,7 +189,7 @@ public class ToParentBlockJoinQuery extends Query {
if (scorer != null && scorer.advance(doc) == doc) {
return scorer.explain(context.docBase);
}
- return new ComplexExplanation(false, 0.0f, "Not a match");
+ return Explanation.noMatch("Not a match");
}
}
@@ -414,8 +413,7 @@ public class ToParentBlockJoinQuery extends Query {
public Explanation explain(int docBase) throws IOException {
int start = docBase + prevParentDoc + 1; // +1 b/c prevParentDoc is previous parent doc
int end = docBase + parentDoc - 1; // -1 b/c parentDoc is parent doc
- return new ComplexExplanation(
- true, score(), String.format(Locale.ROOT, "Score based on child doc range from %d to %d", start, end)
+ return Explanation.match(score(), String.format(Locale.ROOT, "Score based on child doc range from %d to %d", start, end)
);
}
diff --git a/lucene/misc/src/test/org/apache/lucene/search/TestDiversifiedTopDocsCollector.java b/lucene/misc/src/test/org/apache/lucene/search/TestDiversifiedTopDocsCollector.java
index 5349255b626..3455c49af3d 100644
--- a/lucene/misc/src/test/org/apache/lucene/search/TestDiversifiedTopDocsCollector.java
+++ b/lucene/misc/src/test/org/apache/lucene/search/TestDiversifiedTopDocsCollector.java
@@ -454,7 +454,7 @@ public class TestDiversifiedTopDocsCollector extends LuceneTestCase {
@Override
public Explanation explain(int doc, Explanation freq) {
- return new Explanation(Float.intBitsToFloat((int) values.get(doc)),
+ return Explanation.match(Float.intBitsToFloat((int) values.get(doc)),
"indexDocValue(" + scoreValueField + ")");
}
};
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
index edd42e0f83d..f75ce98325b 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreProvider.java
@@ -18,9 +18,11 @@ package org.apache.lucene.queries;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
-import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.IndexReader; // for javadocs
+import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.search.Explanation;
@@ -130,12 +132,13 @@ public class CustomScoreProvider {
for (Explanation valSrcExpl : valSrcExpls) {
valSrcScore *= valSrcExpl.getValue();
}
- Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
- exp.addDetail(subQueryExpl);
+
+ List subs = new ArrayList<>();
+ subs.add(subQueryExpl);
for (Explanation valSrcExpl : valSrcExpls) {
- exp.addDetail(valSrcExpl);
+ subs.add(valSrcExpl);
}
- return exp;
+ return Explanation.match(valSrcScore * subQueryExpl.getValue(), "custom score: product of:", subs);
}
/**
@@ -154,10 +157,7 @@ public class CustomScoreProvider {
if (valSrcExpl != null) {
valSrcScore *= valSrcExpl.getValue();
}
- Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
- exp.addDetail(subQueryExpl);
- exp.addDetail(valSrcExpl);
- return exp;
+ return Explanation.match(valSrcScore * subQueryExpl.getValue(), "custom score: product of:", subQueryExpl, valSrcExpl);
}
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
index 391d6d40251..215fbc8f9cb 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/CustomScoreQuery.java
@@ -28,7 +28,6 @@ import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.FilterScorer;
import org.apache.lucene.search.IndexSearcher;
@@ -244,7 +243,7 @@ public class CustomScoreQuery extends Query {
@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
Explanation explain = doExplain(context, doc);
- return explain == null ? new Explanation(0.0f, "no matching docs") : explain;
+ return explain == null ? Explanation.noMatch("no matching docs") : explain;
}
private Explanation doExplain(LeafReaderContext info, int doc) throws IOException {
@@ -259,11 +258,9 @@ public class CustomScoreQuery extends Query {
}
Explanation customExp = CustomScoreQuery.this.getCustomScoreProvider(info).customExplain(doc,subQueryExpl,valSrcExpls);
float sc = queryWeight * customExp.getValue();
- Explanation res = new ComplexExplanation(
- true, sc, CustomScoreQuery.this.toString() + ", product of:");
- res.addDetail(customExp);
- res.addDetail(new Explanation(queryWeight, "queryWeight"));
- return res;
+ return Explanation.match(
+ sc, CustomScoreQuery.this.toString() + ", product of:",
+ customExp, Explanation.match(queryWeight, "queryWeight"));
}
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/TermsQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/TermsQuery.java
index 980c3abbebe..f0881c8c4c7 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/TermsQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/TermsQuery.java
@@ -34,7 +34,6 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
@@ -377,19 +376,12 @@ public class TermsQuery extends Query implements Accountable {
final Scorer s = scorer(context, context.reader().getLiveDocs());
final boolean exists = (s != null && s.advance(doc) == doc);
- final ComplexExplanation result = new ComplexExplanation();
if (exists) {
- result.setDescription(TermsQuery.this.toString() + ", product of:");
- result.setValue(queryWeight);
- result.setMatch(Boolean.TRUE);
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(queryNorm, "queryNorm"));
+ return Explanation.match(queryWeight, TermsQuery.this.toString() + ", product of:",
+ Explanation.match(getBoost(), "boost"), Explanation.match(queryNorm, "queryNorm"));
} else {
- result.setDescription(TermsQuery.this.toString() + " doesn't match id " + doc);
- result.setValue(0);
- result.setMatch(Boolean.FALSE);
+ return Explanation.noMatch(TermsQuery.this.toString() + " doesn't match id " + doc);
}
- return result;
}
@Override
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
index 11dba012422..8b76a3a7441 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/BoostedQuery.java
@@ -26,7 +26,6 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.FilterScorer;
import org.apache.lucene.search.IndexSearcher;
@@ -115,11 +114,7 @@ public class BoostedQuery extends Query {
}
FunctionValues vals = boostVal.getValues(fcontext, readerContext);
float sc = subQueryExpl.getValue() * vals.floatVal(doc);
- Explanation res = new ComplexExplanation(
- true, sc, BoostedQuery.this.toString() + ", product of:");
- res.addDetail(subQueryExpl);
- res.addDetail(vals.explain(doc));
- return res;
+ return Explanation.match(sc, BoostedQuery.this.toString() + ", product of:", subQueryExpl, vals.explain(doc));
}
}
@@ -160,11 +155,7 @@ public class BoostedQuery extends Query {
return subQueryExpl;
}
float sc = subQueryExpl.getValue() * vals.floatVal(doc);
- Explanation res = new ComplexExplanation(
- true, sc, BoostedQuery.this.toString() + ", product of:");
- res.addDetail(subQueryExpl);
- res.addDetail(vals.explain(doc));
- return res;
+ return Explanation.match(sc, BoostedQuery.this.toString() + ", product of:", subQueryExpl, vals.explain(doc));
}
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
index 0b68705400e..10a35a1f976 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionQuery.java
@@ -24,7 +24,6 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -170,13 +169,10 @@ public class FunctionQuery extends Query {
public Explanation explain(int doc) throws IOException {
float sc = qWeight * vals.floatVal(doc);
- Explanation result = new ComplexExplanation
- (true, sc, "FunctionQuery(" + func + "), product of:");
-
- result.addDetail(vals.explain(doc));
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(weight.queryNorm,"queryNorm"));
- return result;
+ return Explanation.match(sc, "FunctionQuery(" + func + "), product of:",
+ vals.explain(doc),
+ Explanation.match(getBoost(), "boost"),
+ Explanation.match(weight.queryNorm, "queryNorm"));
}
}
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionValues.java b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionValues.java
index 4b6dead2e8b..019c3c85fb7 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionValues.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/function/FunctionValues.java
@@ -133,7 +133,7 @@ public abstract class FunctionValues {
public void strVal(int doc, String [] vals) { throw new UnsupportedOperationException(); }
public Explanation explain(int doc) {
- return new Explanation(floatVal(doc), toString(doc));
+ return Explanation.match(floatVal(doc), toString(doc));
}
public ValueSourceScorer getScorer(IndexReader reader) {
diff --git a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
index 7a2d38d630e..8d638eae56d 100644
--- a/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
+++ b/lucene/queries/src/test/org/apache/lucene/queries/TestCustomScoreQuery.java
@@ -17,7 +17,18 @@ package org.apache.lucene.queries;
* limitations under the License.
*/
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.FunctionTestSetup;
import org.apache.lucene.queries.function.ValueSource;
@@ -33,15 +44,6 @@ import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.junit.BeforeClass;
import org.junit.Test;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.index.Term;
/**
* Test CustomScoreQuery search.
@@ -94,13 +96,13 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
@Override
public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
- float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
- Explanation exp = new Explanation(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
- exp.addDetail(subQueryExpl);
+ List subs = new ArrayList<>();
+ subs.add(subQueryExpl);
if (valSrcExpl != null) {
- exp.addDetail(valSrcExpl);
+ subs.add(valSrcExpl);
}
- return exp;
+ float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
+ return Explanation.match(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:", subs);
}
};
}
@@ -140,17 +142,12 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
if (valSrcExpls.length == 0) {
return subQueryExpl;
}
- Explanation exp = new Explanation(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "sum of:");
- exp.addDetail(subQueryExpl);
- exp.addDetail(valSrcExpls[0]);
if (valSrcExpls.length == 1) {
- exp.setDescription("CustomMulAdd, sum of:");
- return exp;
+ return Explanation.match(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "CustomMulAdd, sum of:", subQueryExpl, valSrcExpls[0]);
+ } else {
+ Explanation exp = Explanation.match(valSrcExpls[0].getValue() + subQueryExpl.getValue(), "sum of:", subQueryExpl, valSrcExpls[0]);
+ return Explanation.match(valSrcExpls[1].getValue() * exp.getValue(), "custom score: product of:", valSrcExpls[1], exp);
}
- Explanation exp2 = new Explanation(valSrcExpls[1].getValue() * exp.getValue(), "custom score: product of:");
- exp2.addDetail(valSrcExpls[1]);
- exp2.addDetail(exp);
- return exp2;
}
};
}
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxOverlapRatioValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxOverlapRatioValueSource.java
index 70d3ddb126d..f5fb14e1822 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxOverlapRatioValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxOverlapRatioValueSource.java
@@ -16,10 +16,13 @@
*/
package org.apache.lucene.spatial.bbox;
-import com.spatial4j.core.shape.Rectangle;
+import java.util.concurrent.atomic.AtomicReference;
+
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Explanation;
+import com.spatial4j.core.shape.Rectangle;
+
/**
* The algorithm is implemented as envelope on envelope (rect on rect) overlays rather than
* complex polygon on complex polygon overlays.
@@ -126,7 +129,7 @@ public class BBoxOverlapRatioValueSource extends BBoxSimilarityValueSource {
}
@Override
- protected double score(Rectangle target, Explanation exp) {
+ protected double score(Rectangle target, AtomicReference exp) {
// calculate "height": the intersection height between two boxes.
double top = Math.min(queryExtent.getMaxY(), target.getMaxY());
double bottom = Math.max(queryExtent.getMinY(), target.getMinY());
@@ -211,25 +214,19 @@ public class BBoxOverlapRatioValueSource extends BBoxSimilarityValueSource {
double score = queryFactor + targetFactor;
if (exp!=null) {
- exp.setValue((float)score);
- exp.setDescription(this.getClass().getSimpleName()+": queryFactor + targetFactor");
-
- Explanation e;//tmp
-
String minSideDesc = minSideLength > 0.0 ? " (minSide="+minSideLength+")" : "";
-
- exp.addDetail( e = new Explanation((float)intersectionArea, "IntersectionArea" + minSideDesc));
- e.addDetail(new Explanation((float)width, "width"));
- e.addDetail(new Explanation((float)height, "height"));
- e.addDetail(new Explanation((float)queryTargetProportion, "queryTargetProportion"));
-
- exp.addDetail( e = new Explanation((float)queryFactor, "queryFactor"));
- e.addDetail(new Explanation((float)queryRatio, "ratio"));
- e.addDetail(new Explanation((float)queryArea, "area of " + queryExtent + minSideDesc));
-
- exp.addDetail( e = new Explanation((float)targetFactor, "targetFactor"));
- e.addDetail(new Explanation((float)targetRatio, "ratio"));
- e.addDetail(new Explanation((float)targetArea, "area of " + target + minSideDesc));
+ exp.set(Explanation.match((float) score,
+ this.getClass().getSimpleName()+": queryFactor + targetFactor",
+ Explanation.match((float)intersectionArea, "IntersectionArea" + minSideDesc,
+ Explanation.match((float)width, "width"),
+ Explanation.match((float)height, "height"),
+ Explanation.match((float)queryTargetProportion, "queryTargetProportion")),
+ Explanation.match((float)queryFactor, "queryFactor",
+ Explanation.match((float)targetRatio, "ratio"),
+ Explanation.match((float)queryArea, "area of " + queryExtent + minSideDesc)),
+ Explanation.match((float)targetFactor, "targetFactor",
+ Explanation.match((float)targetRatio, "ratio"),
+ Explanation.match((float)targetArea, "area of " + target + minSideDesc))));
}
return score;
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
index 3a0bbc74013..4752052bb76 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxSimilarityValueSource.java
@@ -17,7 +17,10 @@ package org.apache.lucene.spatial.bbox;
* limitations under the License.
*/
-import com.spatial4j.core.shape.Rectangle;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
@@ -25,8 +28,7 @@ import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.shape.Rectangle;
/**
* A base class for calculating a spatial relevance rank per document from a provided
@@ -81,10 +83,10 @@ public abstract class BBoxSimilarityValueSource extends ValueSource {
public Explanation explain(int doc) {
final Rectangle rect = (Rectangle) shapeValues.objectVal(doc);
if (rect == null)
- return new Explanation(0, "no rect");
- Explanation exp = new Explanation();
- score(rect, exp);
- return exp;
+ return Explanation.noMatch("no rect");
+ AtomicReference explanation = new AtomicReference<>();
+ score(rect, explanation);
+ return explanation.get();
}
};
}
@@ -95,7 +97,7 @@ public abstract class BBoxSimilarityValueSource extends ValueSource {
* @param exp Optional diagnostic holder.
* @return a score.
*/
- protected abstract double score(Rectangle rect, Explanation exp);
+ protected abstract double score(Rectangle rect, AtomicReference exp);
@Override
public boolean equals(Object o) {
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
index 6c9a92907cc..10fa7b93336 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxValueSource.java
@@ -87,7 +87,7 @@ class BBoxValueSource extends ValueSource {
@Override
public Explanation explain(int doc) {
- return new Explanation(Float.NaN, toString(doc));
+ return Explanation.match(Float.NaN, toString(doc));
}
@Override
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
index 670c4b3c7b6..23476eed9f6 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/serialized/SerializedDVStrategy.java
@@ -266,7 +266,7 @@ public class SerializedDVStrategy extends SpatialStrategy {
@Override
public Explanation explain(int doc) {
- return new Explanation(Float.NaN, toString(doc));
+ return Explanation.match(Float.NaN, toString(doc));
}
@Override
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
index 9216a91b083..703586b118c 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/DistanceToShapeValueSource.java
@@ -17,10 +17,12 @@ package org.apache.lucene.spatial.util;
* limitations under the License.
*/
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.distance.DistanceCalculator;
-import com.spatial4j.core.shape.Point;
-import com.spatial4j.core.shape.Shape;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
@@ -28,8 +30,10 @@ import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
-import java.io.IOException;
-import java.util.Map;
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.distance.DistanceCalculator;
+import com.spatial4j.core.shape.Point;
+import com.spatial4j.core.shape.Shape;
/**
* The distance from a provided Point to a Point retrieved from a ValueSource via
@@ -84,8 +88,9 @@ public class DistanceToShapeValueSource extends ValueSource {
@Override
public Explanation explain(int doc) {
Explanation exp = super.explain(doc);
- exp.addDetail(shapeValues.explain(doc));
- return exp;
+ List details = new ArrayList<>(Arrays.asList(exp.getDetails()));
+ details.add(shapeValues.explain(doc));
+ return Explanation.match(exp.getValue(), exp.getDescription(), details);
}
};
}
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
index c7b7253fbce..b08260ab8a9 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapeAreaValueSource.java
@@ -18,10 +18,14 @@ package org.apache.lucene.spatial.util;
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.shape.Shape;
+
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
@@ -83,8 +87,9 @@ public class ShapeAreaValueSource extends ValueSource {
@Override
public Explanation explain(int doc) {
Explanation exp = super.explain(doc);
- exp.addDetail(shapeValues.explain(doc));
- return exp;
+ List details = new ArrayList<>(Arrays.asList(exp.getDetails()));
+ details.add(shapeValues.explain(doc));
+ return Explanation.match(exp.getValue(), exp.getDescription(), details);
}
};
}
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
index fa013714aea..018b7caaf49 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/util/ShapePredicateValueSource.java
@@ -18,6 +18,7 @@ package org.apache.lucene.spatial.util;
*/
import com.spatial4j.core.shape.Shape;
+
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
@@ -27,6 +28,9 @@ import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.spatial.query.SpatialOperation;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
/**
@@ -79,8 +83,9 @@ public class ShapePredicateValueSource extends ValueSource {
@Override
public Explanation explain(int doc) {
Explanation exp = super.explain(doc);
- exp.addDetail(shapeValues.explain(doc));
- return exp;
+ List details = new ArrayList<>(Arrays.asList(exp.getDetails()));
+ details.add(shapeValues.explain(doc));
+ return Explanation.match(exp.getValue(), exp.getDescription(), details);
}
};
}
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 70e93c173f7..f7bc9837c56 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
@@ -347,7 +347,7 @@ public class CheckHits {
if (expl.getDescription().endsWith("computed from:")) {
return; // something more complicated.
}
- if (detail!=null) {
+ if (detail.length > 0) {
if (detail.length==1) {
// 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
diff --git a/solr/core/src/java/org/apache/solr/schema/LatLonType.java b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
index f6d0681e558..fade2a41fbc 100644
--- a/solr/core/src/java/org/apache/solr/schema/LatLonType.java
+++ b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
@@ -22,10 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import com.spatial4j.core.context.SpatialContext;
-import com.spatial4j.core.distance.DistanceUtils;
-import com.spatial4j.core.shape.Point;
-import com.spatial4j.core.shape.Rectangle;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
@@ -35,7 +31,6 @@ import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.VectorValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@@ -53,6 +48,11 @@ import org.apache.solr.search.QParser;
import org.apache.solr.search.SpatialOptions;
import org.apache.solr.util.SpatialUtils;
+import com.spatial4j.core.context.SpatialContext;
+import com.spatial4j.core.distance.DistanceUtils;
+import com.spatial4j.core.shape.Point;
+import com.spatial4j.core.shape.Rectangle;
+
/**
* Represents a Latitude/Longitude as a 2 dimensional point. Latitude is always specified first.
@@ -495,13 +495,14 @@ class SpatialDistanceQuery extends ExtendedQueryBase implements PostFilter {
String description = SpatialDistanceQuery.this.toString();
- Explanation result = new ComplexExplanation
- (this.doc == doc, sc, description + " product of:");
- // result.addDetail(new Explanation((float)dist, "hsin("+latVals.explain(doc)+","+lonVals.explain(doc)));
- result.addDetail(new Explanation((float)dist, "hsin("+latVals.doubleVal(doc)+","+lonVals.doubleVal(doc)));
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(weight.queryNorm,"queryNorm"));
- return result;
+ if (matched) {
+ return Explanation.match(sc, description + " product of:",
+ Explanation.match((float) dist, "hsin("+latVals.doubleVal(doc)+","+lonVals.doubleVal(doc)),
+ Explanation.match(getBoost(), "boost"),
+ Explanation.match(weight.queryNorm,"queryNorm"));
+ } else {
+ return Explanation.noMatch("No match");
+ }
}
}
diff --git a/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java
index a69e2ad6445..15a6e036642 100644
--- a/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java
+++ b/solr/core/src/java/org/apache/solr/search/JoinQParserPlugin.java
@@ -31,7 +31,6 @@ import org.apache.lucene.index.MultiPostingsEnum;
import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
@@ -568,22 +567,13 @@ class JoinQuery extends Query {
Scorer scorer = scorer(context, context.reader().getLiveDocs());
boolean exists = scorer.advance(doc) == doc;
- ComplexExplanation result = new ComplexExplanation();
-
if (exists) {
- result.setDescription(this.toString()
- + " , product of:");
- result.setValue(queryWeight);
- result.setMatch(Boolean.TRUE);
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(queryNorm,"queryNorm"));
+ return Explanation.match(queryWeight, this.toString() + " , product of:",
+ Explanation.match(getBoost(), "boost"),
+ Explanation.match(queryNorm,"queryNorm"));
} else {
- result.setDescription(this.toString()
- + " doesn't match id " + doc);
- result.setValue(0);
- result.setMatch(Boolean.FALSE);
+ return Explanation.noMatch(this.toString() + " doesn't match id " + doc);
}
- return result;
}
}
diff --git a/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java b/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
index 183cb86433b..a18fb8412ea 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrConstantScoreQuery.java
@@ -7,7 +7,6 @@ import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
@@ -135,22 +134,13 @@ public class SolrConstantScoreQuery extends ConstantScoreQuery implements Extend
ConstantScorer cs = new ConstantScorer(context, this, queryWeight, context.reader().getLiveDocs());
boolean exists = cs.docIdSetIterator.advance(doc) == doc;
- ComplexExplanation result = new ComplexExplanation();
-
if (exists) {
- result.setDescription("ConstantScoreQuery(" + filter
- + "), product of:");
- result.setValue(queryWeight);
- result.setMatch(Boolean.TRUE);
- result.addDetail(new Explanation(getBoost(), "boost"));
- result.addDetail(new Explanation(queryNorm,"queryNorm"));
+ return Explanation.match(queryWeight, "ConstantScoreQuery(" + filter + "), product of:",
+ Explanation.match(getBoost(), "boost"),
+ Explanation.match(queryNorm,"queryNorm"));
} else {
- result.setDescription("ConstantScoreQuery(" + filter
- + ") doesn't match id " + doc);
- result.setValue(0);
- result.setMatch(Boolean.FALSE);
+ return Explanation.noMatch("ConstantScoreQuery(" + filter + ") doesn't match id " + doc);
}
- return result;
}
}
diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
index a98c5ab7b77..dc6a547a677 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
@@ -387,7 +387,7 @@ public class SolrPluginUtils {
Explanation[] details = e.getDetails();
// short circut out
- if (null == details || 0 == details.length) return out;
+ if (0 == details.length) return out;
List> kids
= new ArrayList<>(details.length);