LUCENE-9524: Fix NPE in SpanWeight#explain when no scoring is require… (#1978)

This commit is contained in:
zacharymorn 2020-10-16 10:00:46 -07:00 committed by GitHub
parent 744934c826
commit 6990109f9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 7 deletions

View File

@ -161,6 +161,9 @@ Bug fixes
* LUCENE-9365: FuzzyQuery was missing matches when prefix length was equal to the term length
(Mark Harwood, Mike Drob)
* LUCENE-9524: Fix NPE in SpanWeight#explain when no scoring is required and SpanWeight has null Similarity.SimScorer.
(Zach Chen)
Other
* LUCENE-9312: Allow gradle builds against arbitrary JVMs. (Tomoko Uchida, Dawid Weiss)

View File

@ -20,6 +20,7 @@ package org.apache.lucene.search.spans;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
@ -156,13 +157,19 @@ public abstract class SpanWeight extends Weight {
if (scorer != null) {
int newDoc = scorer.iterator().advance(doc);
if (newDoc == doc) {
float freq = scorer.sloppyFreq();
LeafSimScorer docScorer = new LeafSimScorer(simScorer, context.reader(), field, true);
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);
if (simScorer != null) {
float freq = scorer.sloppyFreq();
LeafSimScorer docScorer = new LeafSimScorer(simScorer, context.reader(), field, true);
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);
} else {
// simScorer won't be set when scoring isn't needed
return Explanation.match(0f, String.format(Locale.ROOT,
"match %s in %s without score", getQuery(), doc));
}
}
}

View File

@ -17,12 +17,22 @@
package org.apache.lucene.search.spans;
import java.io.IOException;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
/**
* TestExplanations subclass focusing on span queries
*/
public class TestSpanExplanations extends BaseExplanationTestCase {
private static final String FIELD_CONTENT = "content";
/* simple SpanTermQueries */
@ -165,4 +175,32 @@ public class TestSpanExplanations extends BaseExplanationTestCase {
qtest(q, new int[] {0,1,3});
}
public void testExplainWithoutScoring() throws IOException {
SpanNearQuery query = new SpanNearQuery(new SpanQuery[]{
new SpanTermQuery(new Term(FIELD_CONTENT, "dolor")),
new SpanTermQuery(new Term(FIELD_CONTENT, "lorem"))},
0,
true);
try (Directory rd = newDirectory()) {
try (IndexWriter writer = new IndexWriter(rd, newIndexWriterConfig(analyzer))) {
Document doc = new Document();
doc.add(newTextField(FIELD_CONTENT, "dolor lorem ipsum", Field.Store.YES));
writer.addDocument(doc);
}
try (DirectoryReader reader = DirectoryReader.open(rd)) {
IndexSearcher indexSearcher = newSearcher(reader);
SpanWeight spanWeight = query.createWeight(indexSearcher, ScoreMode.COMPLETE_NO_SCORES, 1f);
final LeafReaderContext ctx = reader.leaves().get(0);
Explanation explanation = spanWeight.explain(ctx, 0);
assertEquals(0f, explanation.getValue());
assertEquals("match spanNear([content:dolor, content:lorem], 0, true) in 0 without score",
explanation.getDescription());
}
}
}
}