multi_match query should produce MatchNoDocs query on unknown fieldname

Currently when the `fields` parameter used in a `multi_match` query contains a
wildcard expression that doesn't resolve to any field name in the target index,
MultiMatchQueryBuilder produces a `null` query. This change changes it to be a
MatchNoDocs query, since returning no documents for this case is already the
current behaviour. Also adding missing field names (with and without wildcards)
to the unit and integration test.
This commit is contained in:
Christoph Büscher 2016-07-28 11:57:17 +02:00
parent 9fa33b6d07
commit 757de805d3
4 changed files with 23 additions and 4 deletions

View File

@ -29,6 +29,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -747,7 +748,11 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
Query query = multiMatchQuery.parse(type, newFieldsBoosts, value, minimumShouldMatch);
if (query == null) {
return null;
if (newFieldsBoosts.isEmpty()) {
return new MatchNoDocsQuery("[" + NAME + "] could not resolve any field names");
} else {
return new MatchNoDocsQuery("[" + NAME + "] parsing resolved to null query");
}
}
return query;
}

View File

@ -280,7 +280,6 @@ public class MatchQuery {
if (zeroTermsQuery == DEFAULT_ZERO_TERMS_QUERY) {
return Queries.newMatchNoDocsQuery("Matching no documents because no terms present.");
}
return Queries.newMatchAllQuery();
}

View File

@ -53,12 +53,17 @@ import static org.hamcrest.CoreMatchers.instanceOf;
public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatchQueryBuilder> {
private static final String MISSING_WILDCARD_FIELD_NAME = "missing_*";
private static final String MISSING_FIELD_NAME = "missing";
@Override
protected MultiMatchQueryBuilder doCreateTestQueryBuilder() {
String fieldName = randomFrom(STRING_FIELD_NAME, INT_FIELD_NAME, DOUBLE_FIELD_NAME, BOOLEAN_FIELD_NAME, DATE_FIELD_NAME);
String fieldName = randomFrom(STRING_FIELD_NAME, INT_FIELD_NAME, DOUBLE_FIELD_NAME, BOOLEAN_FIELD_NAME, DATE_FIELD_NAME,
MISSING_FIELD_NAME, MISSING_WILDCARD_FIELD_NAME);
if (fieldName.equals(DATE_FIELD_NAME)) {
assumeTrue("test with date fields runs only when at least a type is registered", getCurrentTypes().length > 0);
}
// creates the query with random value and field name
Object value;
if (fieldName.equals(STRING_FIELD_NAME)) {
@ -238,6 +243,12 @@ public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatc
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
}
public void testToQueryFieldMissing() throws Exception {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
assertThat(multiMatchQuery("test").field(MISSING_WILDCARD_FIELD_NAME).toQuery(createShardContext()), instanceOf(MatchNoDocsQuery.class));
assertThat(multiMatchQuery("test").field(MISSING_FIELD_NAME).toQuery(createShardContext()), instanceOf(TermQuery.class));
}
public void testFromJson() throws IOException {
String json =
"{\n" +

View File

@ -237,7 +237,8 @@ public class MultiMatchQueryIT extends ESIntegTestCase {
assertNoFailures(searchResponse);
assertFirstHit(searchResponse, hasId("theone"));
String[] fields = {"full_name", "first_name", "last_name", "last_name_phrase", "first_name_phrase", "category_phrase", "category"};
String[] fields = { "full_name", "first_name", "last_name", "last_name_phrase", "first_name_phrase", "category_phrase", "category",
"missing_field", "missing_fields*" };
String[] query = {"marvel","hero", "captain", "america", "15", "17", "1", "5", "ultimate", "Man",
"marvel", "wolferine", "ninja"};
@ -269,6 +270,9 @@ public class MultiMatchQueryIT extends ESIntegTestCase {
.setQuery(matchQueryBuilder).get();
assertThat("field: " + field + " query: " + builder.toString(), multiMatchResp.getHits().getTotalHits(), equalTo(matchResp.getHits().getTotalHits()));
SearchHits hits = multiMatchResp.getHits();
if (field.startsWith("missing")) {
assertEquals(0, hits.hits().length);
}
for (int j = 0; j < hits.hits().length; j++) {
assertThat(hits.getHits()[j].score(), equalTo(matchResp.getHits().getHits()[j].score()));
assertThat(hits.getHits()[j].getId(), equalTo(matchResp.getHits().getHits()[j].getId()));