Add lenient option to match & multi_match queries. #2156
This commit is contained in:
parent
fedd1965ea
commit
b979dfa0be
|
@ -73,8 +73,11 @@ public class MatchQueryBuilder extends BaseQueryBuilder implements BoostableQuer
|
|||
private String minimumShouldMatch;
|
||||
|
||||
private String rewrite = null;
|
||||
|
||||
private String fuzzyRewrite = null;
|
||||
|
||||
private Boolean lenient;
|
||||
|
||||
/**
|
||||
* Constructs a new text query.
|
||||
*/
|
||||
|
@ -161,6 +164,14 @@ public class MatchQueryBuilder extends BaseQueryBuilder implements BoostableQuer
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether format based failures will be ignored.
|
||||
*/
|
||||
public MatchQueryBuilder setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(MatchQueryParser.NAME);
|
||||
|
@ -201,6 +212,10 @@ public class MatchQueryBuilder extends BaseQueryBuilder implements BoostableQuer
|
|||
builder.field("fuzzy_rewrite", fuzzyRewrite);
|
||||
}
|
||||
|
||||
if (lenient != null) {
|
||||
builder.field("lenient", lenient);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
}
|
||||
|
|
|
@ -122,6 +122,8 @@ public class MatchQueryParser implements QueryParser {
|
|||
matchQuery.setRewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull(), null));
|
||||
} else if ("fuzzy_rewrite".equals(currentFieldName) || "fuzzyRewrite".equals(currentFieldName)) {
|
||||
matchQuery.setFuzzyRewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull(), null));
|
||||
} else if ("lenient".equals(currentFieldName)) {
|
||||
matchQuery.setLenient(parser.booleanValue());
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[match] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl
|
|||
|
||||
private Integer tieBreaker;
|
||||
|
||||
private Boolean lenient;
|
||||
|
||||
/**
|
||||
* Constructs a new text query.
|
||||
*/
|
||||
|
@ -152,11 +154,19 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl
|
|||
return this;
|
||||
}
|
||||
|
||||
public MultiMatchQueryBuilder setTieBreaker(Integer tieBreaker) {
|
||||
public MultiMatchQueryBuilder tieBreaker(Integer tieBreaker) {
|
||||
this.tieBreaker = tieBreaker;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether format based failures will be ignored.
|
||||
*/
|
||||
public MultiMatchQueryBuilder lenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(MultiMatchQueryParser.NAME);
|
||||
|
@ -206,6 +216,10 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl
|
|||
builder.field("tie_breaker", tieBreaker);
|
||||
}
|
||||
|
||||
if (lenient != null) {
|
||||
builder.field("lenient", lenient);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
|
@ -154,6 +154,8 @@ public class MultiMatchQueryParser implements QueryParser {
|
|||
multiMatchQuery.setUseDisMax(parser.booleanValue());
|
||||
} else if ("tie_breaker".equals(currentFieldName) || "tieBreaker".equals(currentFieldName)) {
|
||||
multiMatchQuery.setTieBreaker(parser.intValue());
|
||||
} else if ("lenient".equals(currentFieldName)) {
|
||||
multiMatchQuery.setLenient(parser.booleanValue());
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[match] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ public class MatchQuery {
|
|||
protected MultiTermQuery.RewriteMethod rewriteMethod;
|
||||
protected MultiTermQuery.RewriteMethod fuzzyRewriteMethod;
|
||||
|
||||
protected boolean lenient;
|
||||
|
||||
public MatchQuery(QueryParseContext parseContext) {
|
||||
this.parseContext = parseContext;
|
||||
}
|
||||
|
@ -108,6 +110,10 @@ public class MatchQuery {
|
|||
this.fuzzyRewriteMethod = fuzzyRewriteMethod;
|
||||
}
|
||||
|
||||
public void setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
}
|
||||
|
||||
public Query parse(Type type, String fieldName, String text) {
|
||||
FieldMapper mapper = null;
|
||||
Term fieldTerm;
|
||||
|
@ -124,11 +130,23 @@ public class MatchQuery {
|
|||
String[] previousTypes = QueryParseContext.setTypesWithPrevious(new String[]{smartNameFieldMappers.docMapper().type()});
|
||||
try {
|
||||
return wrapSmartNameQuery(mapper.fieldQuery(text, parseContext), smartNameFieldMappers, parseContext);
|
||||
} catch (RuntimeException e) {
|
||||
if (lenient) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
QueryParseContext.setTypes(previousTypes);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return wrapSmartNameQuery(mapper.fieldQuery(text, parseContext), smartNameFieldMappers, parseContext);
|
||||
} catch (RuntimeException e) {
|
||||
if (lenient) {
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,16 +51,24 @@ public class MultiMatchQuery extends MatchQuery {
|
|||
|
||||
if (useDisMax) {
|
||||
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(tieBreaker);
|
||||
boolean clauseAdded = false;
|
||||
for (String fieldName : fieldNames) {
|
||||
disMaxQuery.add(parse(type, fieldName, text));
|
||||
Query query = parse(type, fieldName, text);
|
||||
if (query != null) {
|
||||
clauseAdded = true;
|
||||
disMaxQuery.add(query);
|
||||
}
|
||||
return disMaxQuery;
|
||||
}
|
||||
return clauseAdded ? disMaxQuery : null;
|
||||
} else {
|
||||
BooleanQuery booleanQuery = new BooleanQuery();
|
||||
for (String fieldName : fieldNames) {
|
||||
booleanQuery.add(parse(type, fieldName, text), BooleanClause.Occur.SHOULD);
|
||||
Query query = parse(type, fieldName, text);
|
||||
if (query != null) {
|
||||
booleanQuery.add(query, BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
return booleanQuery;
|
||||
}
|
||||
return !booleanQuery.clauses().isEmpty() ? booleanQuery : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
|
||||
package org.elasticsearch.test.integration.search.query;
|
||||
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.index.query.*;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.search.facet.FacetBuilders;
|
||||
import org.elasticsearch.test.integration.AbstractNodesTests;
|
||||
import org.testng.annotations.AfterClass;
|
||||
|
@ -37,6 +40,8 @@ import static org.elasticsearch.index.query.QueryBuilders.*;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -390,6 +395,25 @@ public class SimpleQueryTests extends AbstractNodesTests {
|
|||
.execute().actionGet();
|
||||
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
||||
assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));
|
||||
|
||||
// Test lenient
|
||||
client.prepareIndex("test", "type1", "3").setSource("field1", "value7", "field2", "value8", "field3", 5).execute().actionGet();
|
||||
client.admin().indices().prepareRefresh("test").execute().actionGet();
|
||||
|
||||
builder = QueryBuilders.multiMatchQuery("value1", "field1", "field2", "field3");
|
||||
try {
|
||||
client.prepareSearch()
|
||||
.setQuery(builder)
|
||||
.execute().actionGet();
|
||||
fail("Exception expected");
|
||||
} catch (SearchPhaseExecutionException e) {
|
||||
assertThat(e.shardFailures()[0].status(), equalTo(RestStatus.BAD_REQUEST));
|
||||
}
|
||||
|
||||
builder.lenient(true);
|
||||
searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();
|
||||
assertThat(searchResponse.hits().totalHits(), equalTo(1l));
|
||||
assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue