mirror of https://github.com/apache/lucene.git
LUCENE-7206: Improve the ToParentBlockJoinQuery's explain by including the explain of the best matching child doc
This commit is contained in:
parent
dc67fcde51
commit
af98f35d21
|
@ -149,6 +149,9 @@ Other
|
|||
* SOLR-9109/SOLR-9121: Allow specification of a custom Ivy settings file via system
|
||||
property "ivysettings.xml". (Misha Dmitriev, Christine Poerschke, Uwe Schindler, Steve Rowe)
|
||||
|
||||
* LUCENE-7206: Improve the ToParentBlockJoinQuery's explain by including the explain
|
||||
of the best matching child doc. (Ilya Kasnacheev, Jeff Evans via Martijn van Groningen)
|
||||
|
||||
Build
|
||||
|
||||
* LUCENE-7292: Use '-release' instead of '-source/-target' during
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
package org.apache.lucene.search.join;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -184,7 +186,7 @@ public class ToParentBlockJoinQuery extends Query {
|
|||
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.docBase);
|
||||
return scorer.explain(context, childWeight);
|
||||
}
|
||||
return Explanation.noMatch("Not a match");
|
||||
}
|
||||
|
@ -436,10 +438,24 @@ public class ToParentBlockJoinQuery extends Query {
|
|||
return parentFreq;
|
||||
}
|
||||
|
||||
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 Explanation.match(score(), String.format(Locale.ROOT, "Score based on child doc range from %d to %d", start, end)
|
||||
public Explanation explain(LeafReaderContext context, Weight childWeight) throws IOException {
|
||||
int start = context.docBase + prevParentDoc + 1; // +1 b/c prevParentDoc is previous parent doc
|
||||
int end = context.docBase + parentDoc - 1; // -1 b/c parentDoc is parent doc
|
||||
|
||||
Explanation bestChild = 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() > bestChild.getValue()) {
|
||||
bestChild = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.lucene.analysis.MockAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
|
@ -50,6 +52,7 @@ import org.apache.lucene.search.BooleanClause.Occur;
|
|||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.BoostQuery;
|
||||
import org.apache.lucene.search.CheckHits;
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.apache.lucene.search.FieldDoc;
|
||||
|
@ -231,6 +234,8 @@ public class TestBlockJoin extends LuceneTestCase {
|
|||
|
||||
ToParentBlockJoinCollector c = new ToParentBlockJoinCollector(Sort.RELEVANCE, 1, true, true);
|
||||
|
||||
CheckHits.checkHitCollector(random(), fullQuery.build(), "country", s, new int[] {2});
|
||||
|
||||
s.search(fullQuery.build(), c);
|
||||
|
||||
TopGroups<Integer> results = c.getTopGroups(childJoinQuery, null, 0, 10, 0, true);
|
||||
|
@ -869,7 +874,16 @@ public class TestBlockJoin extends LuceneTestCase {
|
|||
//System.out.println(" hit docID=" + hit.doc + " childId=" + childId + " parentId=" + document.get("parentID"));
|
||||
assertTrue(explanation.isMatch());
|
||||
assertEquals(hit.score, explanation.getValue(), 0.0f);
|
||||
assertEquals(String.format(Locale.ROOT, "Score based on child doc range from %d to %d", hit.doc - 1 - childId, hit.doc - 1), explanation.getDescription());
|
||||
Matcher m = Pattern.compile("Score based on ([0-9]+) child docs in range from ([0-9]+) to ([0-9]+), best match:").matcher(explanation.getDescription());
|
||||
assertTrue("Block Join description not matches", m.matches());
|
||||
assertTrue("Matched children not positive", Integer.parseInt(m.group(1)) > 0);
|
||||
assertEquals("Wrong child range start", hit.doc - 1 - childId, Integer.parseInt(m.group(2)));
|
||||
assertEquals("Wrong child range end", hit.doc - 1, Integer.parseInt(m.group(3)));
|
||||
Explanation childWeightExplanation = explanation.getDetails()[0];
|
||||
if ("sum of:".equals(childWeightExplanation.getDescription())) {
|
||||
childWeightExplanation = childWeightExplanation.getDetails()[0];
|
||||
}
|
||||
assertTrue("Wrong child weight description", childWeightExplanation.getDescription().startsWith("weight(child"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -346,6 +346,10 @@ public class CheckHits {
|
|||
if (expl.getDescription().endsWith("computed from:")) {
|
||||
return; // something more complicated.
|
||||
}
|
||||
String descr = expl.getDescription().toLowerCase(Locale.ROOT);
|
||||
if (descr.startsWith("score based on ") && descr.contains("child docs in range")) {
|
||||
Assert.assertTrue("Child doc explanations are missing", detail.length > 0);
|
||||
}
|
||||
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),
|
||||
|
@ -357,7 +361,6 @@ public class CheckHits {
|
|||
// - end with one of: "product of:", "sum of:", "max of:", or
|
||||
// - have "max plus <x> times others" (where <x> is float).
|
||||
float x = 0;
|
||||
String descr = expl.getDescription().toLowerCase(Locale.ROOT);
|
||||
boolean productOf = descr.endsWith("product of:");
|
||||
boolean sumOf = descr.endsWith("sum of:");
|
||||
boolean maxOf = descr.endsWith("max of:");
|
||||
|
|
Loading…
Reference in New Issue