Skip to content

Commit e8bb396

Browse files
authored
Prevent NullPointerException in SourceConfirmedTextQuery (#80472) (#80474)
Prevents a npe when the field that does not exists in the index
1 parent 7937f67 commit e8bb396

File tree

2 files changed

+39
-20
lines changed

2 files changed

+39
-20
lines changed

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/extras/SourceConfirmedTextQuery.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -219,28 +219,35 @@ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float bo
219219
throw new IllegalStateException("Query " + in + " doesn't have any term");
220220
}
221221
final String field = terms.iterator().next().field();
222-
final Map<Term, TermStates> termStates = new HashMap<>();
223-
final List<TermStatistics> termStats = new ArrayList<>();
224-
for (Term term : terms) {
225-
TermStates ts = termStates.computeIfAbsent(term, t -> {
226-
try {
227-
return TermStates.build(searcher.getTopReaderContext(), t, scoreMode.needsScores());
228-
} catch (IOException e) {
229-
throw new UncheckedIOException(e);
230-
}
231-
});
232-
if (scoreMode.needsScores()) {
233-
if (ts.docFreq() > 0) {
234-
termStats.add(searcher.termStatistics(term, ts.docFreq(), ts.totalTermFreq()));
222+
final CollectionStatistics collectionStatistics = searcher.collectionStatistics(field);
223+
final SimScorer simScorer;
224+
final Weight approximationWeight;
225+
if (collectionStatistics == null) {
226+
// field does not exist in the index
227+
simScorer = null;
228+
approximationWeight = null;
229+
} else {
230+
final Map<Term, TermStates> termStates = new HashMap<>();
231+
final List<TermStatistics> termStats = new ArrayList<>();
232+
for (Term term : terms) {
233+
TermStates ts = termStates.computeIfAbsent(term, t -> {
234+
try {
235+
return TermStates.build(searcher.getTopReaderContext(), t, scoreMode.needsScores());
236+
} catch (IOException e) {
237+
throw new UncheckedIOException(e);
238+
}
239+
});
240+
if (scoreMode.needsScores()) {
241+
if (ts.docFreq() > 0) {
242+
termStats.add(searcher.termStatistics(term, ts.docFreq(), ts.totalTermFreq()));
243+
}
244+
} else {
245+
termStats.add(new TermStatistics(term.bytes(), 1, 1L));
235246
}
236-
} else {
237-
termStats.add(new TermStatistics(term.bytes(), 1, 1L));
238247
}
248+
simScorer = searcher.getSimilarity().scorer(boost, collectionStatistics, termStats.toArray(TermStatistics[]::new));
249+
approximationWeight = searcher.createWeight(approximate(in), ScoreMode.COMPLETE_NO_SCORES, 1f);
239250
}
240-
final SimScorer simScorer = searcher.getSimilarity()
241-
.scorer(boost, searcher.collectionStatistics(field), termStats.toArray(TermStatistics[]::new));
242-
final Weight approximationWeight = searcher.createWeight(approximate(in), ScoreMode.COMPLETE_NO_SCORES, 1f);
243-
244251
return new Weight(this) {
245252

246253
@Override
@@ -272,7 +279,7 @@ public Explanation explain(LeafReaderContext context, int doc) throws IOExceptio
272279

273280
@Override
274281
public RuntimePhraseScorer scorer(LeafReaderContext context) throws IOException {
275-
final Scorer approximationScorer = approximationWeight.scorer(context);
282+
final Scorer approximationScorer = approximationWeight != null ? approximationWeight.scorer(context) : null;
276283
if (approximationScorer == null) {
277284
return null;
278285
}

modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/extras/SourceConfirmedTextQueryTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,4 +417,16 @@ public void testApproximation() {
417417
).build();
418418
assertEquals(approximation, SourceConfirmedTextQuery.approximate(phrasePrefixQuery));
419419
}
420+
421+
public void testEmptyIndex() throws Exception {
422+
try (Directory dir = newDirectory(); IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(Lucene.STANDARD_ANALYZER))) {
423+
try (IndexReader reader = DirectoryReader.open(w)) {
424+
IndexSearcher searcher = new IndexSearcher(reader);
425+
PhraseQuery query = new PhraseQuery("body", "a", "b");
426+
Query sourceConfirmedPhraseQuery = new SourceConfirmedTextQuery(query, SOURCE_FETCHER_PROVIDER, Lucene.STANDARD_ANALYZER);
427+
assertEquals(0, searcher.count(sourceConfirmedPhraseQuery));
428+
}
429+
}
430+
}
431+
420432
}

0 commit comments

Comments
 (0)