mirror of https://github.com/apache/lucene.git
Add sub query explanations in DisjunctionMaxQuery#explain on no-match (#13362)
This commit is contained in:
parent
dae7181a97
commit
8e5409c9b4
|
@ -293,6 +293,8 @@ Improvements
|
|||
* GITHUB#12966: Move most of the responsibility from TaxonomyFacets implementations to TaxonomyFacets itself.
|
||||
This reduces code duplication and enables future development. (Stefan Vodita)
|
||||
|
||||
* GITHUB#13362: Add sub query explanations to DisjunctionMaxQuery, if the overall query didn't match. (Tim Grein)
|
||||
|
||||
Optimizations
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -213,12 +213,13 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
|
|||
boolean match = false;
|
||||
double max = 0;
|
||||
double otherSum = 0;
|
||||
List<Explanation> subs = new ArrayList<>();
|
||||
List<Explanation> subsOnMatch = new ArrayList<>();
|
||||
List<Explanation> subsOnNoMatch = new ArrayList<>();
|
||||
for (Weight wt : weights) {
|
||||
Explanation e = wt.explain(context, doc);
|
||||
if (e.isMatch()) {
|
||||
match = true;
|
||||
subs.add(e);
|
||||
subsOnMatch.add(e);
|
||||
double score = e.getValue().doubleValue();
|
||||
if (score >= max) {
|
||||
otherSum += max;
|
||||
|
@ -226,6 +227,8 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
|
|||
} else {
|
||||
otherSum += score;
|
||||
}
|
||||
} else if (match == false) {
|
||||
subsOnNoMatch.add(e);
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
|
@ -234,9 +237,9 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
|
|||
tieBreakerMultiplier == 0.0f
|
||||
? "max of:"
|
||||
: "max plus " + tieBreakerMultiplier + " times others of:";
|
||||
return Explanation.match(score, desc, subs);
|
||||
return Explanation.match(score, desc, subsOnMatch);
|
||||
} else {
|
||||
return Explanation.noMatch("No matching clause");
|
||||
return Explanation.noMatch("No matching clause", subsOnNoMatch);
|
||||
}
|
||||
}
|
||||
} // end of DisjunctionMaxWeight inner class
|
||||
|
|
|
@ -497,6 +497,57 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
|
|||
doTestRandomTopDocs(4, 1.0f, 0.5f, 0.05f, 0f);
|
||||
}
|
||||
|
||||
public void testExplainMatch() throws IOException {
|
||||
// Both match
|
||||
Query sub1 = tq("hed", "elephant");
|
||||
Query sub2 = tq("dek", "elephant");
|
||||
|
||||
final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(Arrays.asList(sub1, sub2), 0.0f);
|
||||
|
||||
final Weight dw = s.createWeight(s.rewrite(dq), ScoreMode.COMPLETE, 1);
|
||||
LeafReaderContext context = (LeafReaderContext) s.getTopReaderContext();
|
||||
Explanation explanation = dw.explain(context, 1);
|
||||
|
||||
assertEquals("max of:", explanation.getDescription());
|
||||
// Two matching sub queries should be included in the explanation details
|
||||
assertEquals(2, explanation.getDetails().length);
|
||||
}
|
||||
|
||||
public void testExplainNoMatch() throws IOException {
|
||||
// No match
|
||||
Query sub1 = tq("abc", "elephant");
|
||||
Query sub2 = tq("def", "elephant");
|
||||
|
||||
final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(Arrays.asList(sub1, sub2), 0.0f);
|
||||
|
||||
final Weight dw = s.createWeight(s.rewrite(dq), ScoreMode.COMPLETE, 1);
|
||||
LeafReaderContext context = (LeafReaderContext) s.getTopReaderContext();
|
||||
Explanation explanation = dw.explain(context, 1);
|
||||
|
||||
assertEquals("No matching clause", explanation.getDescription());
|
||||
// Two non-matching sub queries should be included in the explanation details
|
||||
assertEquals(2, explanation.getDetails().length);
|
||||
}
|
||||
|
||||
public void testExplainMatch_OneNonMatchingSubQuery_NotIncludedInExplanation()
|
||||
throws IOException {
|
||||
// Matches
|
||||
Query sub1 = tq("hed", "elephant");
|
||||
|
||||
// Doesn't match
|
||||
Query sub2 = tq("def", "elephant");
|
||||
|
||||
final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(Arrays.asList(sub1, sub2), 0.0f);
|
||||
|
||||
final Weight dw = s.createWeight(s.rewrite(dq), ScoreMode.COMPLETE, 1);
|
||||
LeafReaderContext context = (LeafReaderContext) s.getTopReaderContext();
|
||||
Explanation explanation = dw.explain(context, 1);
|
||||
|
||||
assertEquals("max of:", explanation.getDescription());
|
||||
// Only the matching sub query (sub1) should be included in the explanation details
|
||||
assertEquals(1, explanation.getDetails().length);
|
||||
}
|
||||
|
||||
private void doTestRandomTopDocs(int numFields, double... freqs) throws IOException {
|
||||
assert numFields == freqs.length;
|
||||
Directory dir = newDirectory();
|
||||
|
|
|
@ -417,7 +417,7 @@ public class CheckHits {
|
|||
if (descr.startsWith("score based on ") && descr.contains("child docs in range")) {
|
||||
assertTrue("Child doc explanations are missing", detail.length > 0);
|
||||
}
|
||||
if (detail.length > 0) {
|
||||
if (detail.length > 0 && expl.isMatch()) {
|
||||
if (detail.length == 1 && COMPUTED_FROM_PATTERN.matcher(descr).matches() == false) {
|
||||
// simple containment, unless it's a freq of: (which lets a query explain how the freq is
|
||||
// calculated),
|
||||
|
|
Loading…
Reference in New Issue