_all: Stop NPE querying _all when it doesn't exist

This can happen in two ways:
1. The _all field is disabled.
2. There are documents in the index, the _all field is enabled, but there are
no fields in any of the documents.

In both of these cases we now rewrite the query to a MatchNoDocsQuery which
should be safe because there isn't anything to match.

Closes #12439
This commit is contained in:
Nik Everett 2015-07-27 15:36:34 -04:00
parent 15ea07f8c0
commit d7491515b2
2 changed files with 29 additions and 3 deletions

View File

@ -25,6 +25,7 @@ import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms; import org.apache.lucene.index.Terms;
import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.payloads.AveragePayloadFunction; import org.apache.lucene.search.payloads.AveragePayloadFunction;
@ -124,14 +125,21 @@ public final class AllTermQuery extends PayloadTermQuery {
@Override @Override
public Query rewrite(IndexReader reader) throws IOException { public Query rewrite(IndexReader reader) throws IOException {
boolean fieldExists = false;
boolean hasPayloads = false; boolean hasPayloads = false;
for (LeafReaderContext context : reader.leaves()) { for (LeafReaderContext context : reader.leaves()) {
final Terms terms = context.reader().terms(term.field()); final Terms terms = context.reader().terms(term.field());
if (terms != null) {
fieldExists = true;
if (terms.hasPayloads()) { if (terms.hasPayloads()) {
hasPayloads = true; hasPayloads = true;
break; break;
} }
} }
}
if (fieldExists == false) {
return new MatchNoDocsQuery();
}
if (hasPayloads == false) { if (hasPayloads == false) {
TermQuery rewritten = new TermQuery(term); TermQuery rewritten = new TermQuery(term);
rewritten.setBoost(getBoost()); rewritten.setBoost(getBoost());

View File

@ -1867,6 +1867,24 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest {
assertHitCount(searchResponse, 1l); assertHitCount(searchResponse, 1l);
} }
@Test
public void testAllFieldEmptyMapping() throws Exception {
client().prepareIndex("myindex", "mytype").setId("1").setSource("{}").setRefresh(true).get();
SearchResponse response = client().prepareSearch("myindex").setQuery(matchQuery("_all", "foo")).get();
assertNoFailures(response);
}
@Test
public void testAllDisabledButQueried() throws Exception {
createIndex("myindex");
assertAcked(client().admin().indices().preparePutMapping("myindex").setType("mytype").setSource(
jsonBuilder().startObject().startObject("mytype").startObject("_all").field("enabled", false)));
client().prepareIndex("myindex", "mytype").setId("1").setSource("bar", "foo").setRefresh(true).get();
SearchResponse response = client().prepareSearch("myindex").setQuery(matchQuery("_all", "foo")).get();
assertNoFailures(response);
assertHitCount(response, 0);
}
@Test @Test
public void testIndicesQuery() throws Exception { public void testIndicesQuery() throws Exception {
createIndex("index1", "index2", "index3"); createIndex("index1", "index2", "index3");