Skip to content

Commit

Permalink
Add sub query explanations in DisjunctionMaxQuery#explain on no-match (
Browse files Browse the repository at this point in the history
  • Loading branch information
timgrein authored and jpountz committed May 14, 2024
1 parent b1470b9 commit a6d76fc
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 5 deletions.
2 changes: 2 additions & 0 deletions lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,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
---------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,22 @@ public Explanation explain(LeafReaderContext context, int doc) throws IOExceptio
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;
max = score;
} else {
otherSum += score;
}
} else if (match == false) {
subsOnNoMatch.add(e);
}
}
if (match) {
Expand All @@ -234,9 +237,9 @@ public Explanation explain(LeafReaderContext context, int doc) throws IOExceptio
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,57 @@ public void testRandomTopDocs() throws Exception {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ public static void verifyExplanation(
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),
Expand Down

0 comments on commit a6d76fc

Please sign in to comment.