Merge pull request #19665 from cbuescher/missing-field-MultiMatchQuery
`multi_match` query should produce MatchNoDocs query on unknown field
This commit is contained in:
commit
87a4995bed
|
@ -745,11 +745,7 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
|
|||
|
||||
Map<String, Float> newFieldsBoosts = handleFieldsMatchPattern(context.getMapperService(), fieldsBoosts);
|
||||
|
||||
Query query = multiMatchQuery.parse(type, newFieldsBoosts, value, minimumShouldMatch);
|
||||
if (query == null) {
|
||||
return null;
|
||||
}
|
||||
return query;
|
||||
return multiMatchQuery.parse(type, newFieldsBoosts, value, minimumShouldMatch);
|
||||
}
|
||||
|
||||
private static Map<String, Float> handleFieldsMatchPattern(MapperService mapperService, Map<String, Float> fieldsBoosts) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,14 +23,15 @@ import org.apache.lucene.analysis.Analyzer;
|
|||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queries.BlendedTermQuery;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.BoostQuery;
|
||||
import org.apache.lucene.search.DisjunctionMaxQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.query.AbstractQueryBuilder;
|
||||
|
@ -72,28 +73,31 @@ public class MultiMatchQuery extends MatchQuery {
|
|||
}
|
||||
|
||||
public Query parse(MultiMatchQueryBuilder.Type type, Map<String, Float> fieldNames, Object value, String minimumShouldMatch) throws IOException {
|
||||
Query result;
|
||||
if (fieldNames.size() == 1) {
|
||||
Map.Entry<String, Float> fieldBoost = fieldNames.entrySet().iterator().next();
|
||||
Float boostValue = fieldBoost.getValue();
|
||||
return parseAndApply(type.matchQueryType(), fieldBoost.getKey(), value, minimumShouldMatch, boostValue);
|
||||
result = parseAndApply(type.matchQueryType(), fieldBoost.getKey(), value, minimumShouldMatch, boostValue);
|
||||
} else {
|
||||
final float tieBreaker = groupTieBreaker == null ? type.tieBreaker() : groupTieBreaker;
|
||||
switch (type) {
|
||||
case PHRASE:
|
||||
case PHRASE_PREFIX:
|
||||
case BEST_FIELDS:
|
||||
case MOST_FIELDS:
|
||||
queryBuilder = new QueryBuilder(tieBreaker);
|
||||
break;
|
||||
case CROSS_FIELDS:
|
||||
queryBuilder = new CrossFieldsQueryBuilder(tieBreaker);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("No such type: " + type);
|
||||
}
|
||||
final List<? extends Query> queries = queryBuilder.buildGroupedQueries(type, fieldNames, value, minimumShouldMatch);
|
||||
result = queryBuilder.combineGrouped(queries);
|
||||
}
|
||||
|
||||
final float tieBreaker = groupTieBreaker == null ? type.tieBreaker() : groupTieBreaker;
|
||||
switch (type) {
|
||||
case PHRASE:
|
||||
case PHRASE_PREFIX:
|
||||
case BEST_FIELDS:
|
||||
case MOST_FIELDS:
|
||||
queryBuilder = new QueryBuilder(tieBreaker);
|
||||
break;
|
||||
case CROSS_FIELDS:
|
||||
queryBuilder = new CrossFieldsQueryBuilder(tieBreaker);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("No such type: " + type);
|
||||
}
|
||||
final List<? extends Query> queries = queryBuilder.buildGroupedQueries(type, fieldNames, value, minimumShouldMatch);
|
||||
return queryBuilder.combineGrouped(queries);
|
||||
assert result != null;
|
||||
return result;
|
||||
}
|
||||
|
||||
private QueryBuilder queryBuilder;
|
||||
|
@ -127,9 +131,9 @@ public class MultiMatchQuery extends MatchQuery {
|
|||
return parseAndApply(type, field, value, minimumShouldMatch, boostValue);
|
||||
}
|
||||
|
||||
public Query combineGrouped(List<? extends Query> groupQuery) {
|
||||
private Query combineGrouped(List<? extends Query> groupQuery) {
|
||||
if (groupQuery == null || groupQuery.isEmpty()) {
|
||||
return null;
|
||||
return new MatchNoDocsQuery("[multi_match] list of group queries was empty");
|
||||
}
|
||||
if (groupQuery.size() == 1) {
|
||||
return groupQuery.get(0);
|
||||
|
|
|
@ -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" +
|
||||
|
|
|
@ -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()));
|
||||
|
|
Loading…
Reference in New Issue