Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToParentBlockJoinQuery Explain Support Score Mode (#12245) #12283

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ New Features

Improvements
---------------------
(No changes)

GITHUB#12245: Add support for Score Mode to `ToParentBlockJoinQuery` explain. (Marcus Eagan via Mikhail Khludnev)

Optimizations
---------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public long cost() {
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
BlockJoinScorer scorer = (BlockJoinScorer) scorer(context);
if (scorer != null && scorer.iterator().advance(doc) == doc) {
return scorer.explain(context, in);
return scorer.explain(context, in, scoreMode);
}
return Explanation.noMatch("Not a match");
}
Expand Down Expand Up @@ -392,35 +392,51 @@ private void setScoreAndFreq() throws IOException {
}
this.score = (float) score;
}

public Explanation explain(LeafReaderContext context, Weight childWeight) throws IOException {
/*
* This instance of Explanation requires three parameters, context, childWeight, and scoreMode.
* The scoreMode parameter considers Avg, Total, Min, Max, and None.
* */
public Explanation explain(LeafReaderContext context, Weight childWeight, ScoreMode scoreMode)
throws IOException {
int prevParentDoc = parentBits.prevSetBit(parentApproximation.docID() - 1);
int start =
context.docBase + prevParentDoc + 1; // +1 b/c prevParentDoc is previous parent doc
int end = context.docBase + parentApproximation.docID() - 1; // -1 b/c parentDoc is parent doc

Explanation bestChild = null;
Explanation worstChild = null;

int matches = 0;
for (int childDoc = start; childDoc <= end; childDoc++) {
Explanation child = childWeight.explain(context, childDoc - context.docBase);
if (child.isMatch()) {
matches++;
if (bestChild == null
|| child.getValue().floatValue() > bestChild.getValue().floatValue()) {
|| child.getValue().doubleValue() > bestChild.getValue().doubleValue()) {
bestChild = child;
}
if (worstChild == null
|| child.getValue().doubleValue() < worstChild.getValue().doubleValue()) {
worstChild = child;
}
}
}

assert matches > 0 : "No matches should be handled before.";
Explanation subExplain = scoreMode == ScoreMode.Min ? worstChild : bestChild;
return Explanation.match(
score(),
String.format(
Locale.ROOT,
"Score based on %d child docs in range from %d to %d, best match:",
matches,
start,
end),
bestChild);
this.score(),
formatScoreExplanation(matches, start, end, scoreMode),
subExplain == null ? Collections.emptyList() : Collections.singleton(subExplain));
}

private String formatScoreExplanation(int matches, int start, int end, ScoreMode scoreMode) {
return String.format(
Locale.ROOT,
"Score based on %d child docs in range from %d to %d, using score mode %s",
matches,
start,
end,
scoreMode);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ public void testSimple() throws Exception {
CheckHits.checkHitCollector(random(), fullQuery.build(), "country", s, new int[] {2});

TopDocs topDocs = s.search(fullQuery.build(), 1);

// assertEquals(1, results.totalHitCount);
assertEquals(1, topDocs.totalHits.value);
Document parentDoc = s.storedFields().document(topDocs.scoreDocs[0].doc);
Expand Down Expand Up @@ -890,13 +889,11 @@ public void testRandom() throws Exception {
Explanation explanation = joinS.explain(childJoinQuery, hit.doc);
Document document = joinS.storedFields().document(hit.doc - 1);
int childId = Integer.parseInt(document.get("childID"));
// System.out.println(" hit docID=" + hit.doc + " childId=" + childId + " parentId=" +
// document.get("parentID"));
assertTrue(explanation.isMatch());
assertEquals(hit.score, explanation.getValue().doubleValue(), 0.0f);
Matcher m =
Pattern.compile(
"Score based on ([0-9]+) child docs in range from ([0-9]+) to ([0-9]+), best match:")
"Score based on ([0-9]+) child docs in range from ([0-9]+) to ([0-9]+), using score mode (None|Avg|Min|Max|Total)")
.matcher(explanation.getDescription());
assertTrue("Block Join description not matches", m.matches());
assertTrue("Matched children not positive", Integer.parseInt(m.group(1)) > 0);
Expand Down