Made sure that we never throw IndexMissingException in indices query and filter

It could happen although we internally use IgnoreIndices.MISSING, due to MetaData#concreteIndices contract, which throws IndexMissingException anyway if all requested indices are missing.
In case all the indices specified in the query/filter are missing, we just execute the no_match query/filter, no need to throw any error.

Closes #3428
This commit is contained in:
Luca Cavanna 2013-08-06 10:32:52 +02:00
parent 24434063b6
commit 2cbecd9cb3
3 changed files with 163 additions and 2 deletions

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.indices.IndexMissingException;
import java.io.IOException;
import java.util.ArrayList;
@ -146,7 +147,15 @@ public class IndicesFilterParser implements FilterParser {
}
protected boolean matchesIndices(String currentIndex, String... indices) {
String[] concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
final String[] concreteIndices;
try {
concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
} catch(IndexMissingException e) {
//Although we use IgnoreIndices.MISSING, according to MetaData#concreteIndices contract,
// we get IndexMissing either when we have a single index that is missing or when all indices are missing
return false;
}
for (String index : concreteIndices) {
if (Regex.simpleMatch(index, currentIndex)) {
return true;

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.indices.IndexMissingException;
import java.io.IOException;
import java.util.ArrayList;
@ -144,7 +145,15 @@ public class IndicesQueryParser implements QueryParser {
}
protected boolean matchesIndices(String currentIndex, String... indices) {
String[] concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
final String[] concreteIndices;
try {
concreteIndices = clusterService.state().metaData().concreteIndices(indices, IgnoreIndices.MISSING, true);
} catch(IndexMissingException e) {
//Although we use IgnoreIndices.MISSING, according to MetaData#concreteIndices contract,
// we get IndexMissing either when we have a single index that is missing or when all indices are missing
return false;
}
for (String index : concreteIndices) {
if (Regex.simpleMatch(index, currentIndex)) {
return true;

View File

@ -1686,6 +1686,149 @@ public class SimpleQueryTests extends ElasticsearchIntegrationTest {
assertSearchHits(searchResponse, "1", "2");
}
@Test
public void testIndicesQueryMissingIndices() throws IOException {
createIndex("index1");
createIndex("index2");
ensureGreen();
client().prepareIndex("index1", "type1", "1").setSource("field", "match").get();
client().prepareIndex("index1", "type1", "2").setSource("field", "no_match").get();
client().prepareIndex("index2", "type1", "10").setSource("field", "match").get();
client().prepareIndex("index2", "type1", "20").setSource("field", "no_match").get();
client().prepareIndex("index3", "type1", "100").setSource("field", "match").get();
client().prepareIndex("index3", "type1", "200").setSource("field", "no_match").get();
refresh();
//all indices are missing
SearchResponse searchResponse = client().prepareSearch().setQuery(
indicesQuery(termQuery("field", "missing"), "test1", "test2", "test3")
.noMatchQuery(termQuery("field", "match"))).get();
assertHitCount(searchResponse, 3l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index1".equals(hit.index())) {
assertThat(hit, hasId("1"));
} else if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index1, index2 or index3");
}
}
//only one index specified, which is missing
searchResponse = client().prepareSearch().setQuery(
indicesQuery(termQuery("field", "missing"), "test1")
.noMatchQuery(termQuery("field", "match"))).get();
assertHitCount(searchResponse, 3l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index1".equals(hit.index())) {
assertThat(hit, hasId("1"));
} else if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index1, index2 or index3");
}
}
//more than one index specified, one of them is missing
searchResponse = client().prepareSearch().setQuery(
indicesQuery(termQuery("field", "missing"), "index1", "test1")
.noMatchQuery(termQuery("field", "match"))).get();
assertHitCount(searchResponse, 2l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index2 or index3");
}
}
}
@Test
public void testIndicesFilterMissingIndices() throws IOException {
createIndex("index1");
createIndex("index2");
ensureGreen();
client().prepareIndex("index1", "type1", "1").setSource("field", "match").get();
client().prepareIndex("index1", "type1", "2").setSource("field", "no_match").get();
client().prepareIndex("index2", "type1", "10").setSource("field", "match").get();
client().prepareIndex("index2", "type1", "20").setSource("field", "no_match").get();
client().prepareIndex("index3", "type1", "100").setSource("field", "match").get();
client().prepareIndex("index3", "type1", "200").setSource("field", "no_match").get();
refresh();
//all indices are missing
SearchResponse searchResponse = client().prepareSearch().setQuery(
filteredQuery(matchAllQuery(),
indicesFilter(termFilter("field", "missing"), "test1", "test2", "test3")
.noMatchFilter(termFilter("field", "match")))).get();
assertHitCount(searchResponse, 3l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index1".equals(hit.index())) {
assertThat(hit, hasId("1"));
} else if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index1, index2 or index3");
}
}
//only one index specified, which is missing
searchResponse = client().prepareSearch().setQuery(
filteredQuery(matchAllQuery(),
indicesFilter(termFilter("field", "missing"), "test1")
.noMatchFilter(termFilter("field", "match")))).get();
assertHitCount(searchResponse, 3l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index1".equals(hit.index())) {
assertThat(hit, hasId("1"));
} else if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index1, index2 or index3");
}
}
//more than one index specified, one of them is missing
searchResponse = client().prepareSearch().setQuery(
filteredQuery(matchAllQuery(),
indicesFilter(termFilter("field", "missing"), "index1", "test1")
.noMatchFilter(termFilter("field", "match")))).get();
assertHitCount(searchResponse, 2l);
for (SearchHit hit : searchResponse.getHits().getHits()) {
if ("index2".equals(hit.index())) {
assertThat(hit, hasId("10"));
} else if ("index3".equals(hit.index())) {
assertThat(hit, hasId("100"));
} else {
fail("Returned documents should belong to either index2 or index3");
}
}
}
@Test
public void testMinScore() {
createIndex("test");